2011-09-07 13 views
5

Sustitución de métodos en Java tienen las siguientes características:Sustitución de métodos limitaciones en java

1> El método Overrinding deben tener la misma lista de argumentos como el método de la clase dominante.

2> El tipo de devolución debe ser la misma/subclase del tipo de devolución para el método de clase principal.

3> El nivel de acceso debe ser igual o menos restrictivo que el método de la clase padre.

4> El método modificado puede arrojar la misma excepción o más estrecha y no una más amplia.

* sólo quería saber por qué es tan para el punto *

* 2 - ¿por qué no subclase de una superclase? *

3 - ¿por qué el nivel de acceso debería ser menos restrictivo?

4 - why it should throw narrow exception?

Según mi entender es sólo que si yo estoy creando un refrence clase padre para crear un objeto de clase del niño y tratando de correr por cada uno de los escenarios luego

Asumamos A es la clase padre y B es clase hija teniendo ambas método printAndReturnSomething()

public class A{ 

     public B printAndReturnSomething(){ 
       S.O.P("Inside A Print"); 
       return new B(); 
       } 
} 

Ahora tenemos la clase hija B como

public class B extends A{ 
     public A printAndReturnSomething(){ // I know this isn't possible to return A but had it been then 
       S.O.P("Inside A Print"); 
       return new A(); 
       } 
} 

Ahora bien, si hago algo como esto

A a =new B(); 

y ahora ya que tengo una referencia de A, así que esperar que el tipo de retorno sea de tipo B

B returnedValue=a.printAndReturnSomething(); // But it actually calls the child class method and hence returns A. So here comes the contradiction. 

Similaraly para el escenarios 3 y 4. ¿Es correcto mi entendimiento? ¿Me estoy perdiendo algo más relevante?

Respuesta

5

Todo esto puede resumirse diciendo que "una subclase debe comportarse como si fuera una superclase". Entonces, si Derived se extiende a Base y tengo un objeto x del tipo Derived, entonces quiero que se comporte exactamente como si fuera del tipo Base.

Así que si vuelve x.foo() algún tipo T y Base::foo() devuelve un tipo de S, entonces yo quiero ser capaz de tratar x.foo() como S, por lo T mejor que sea la misma o una subclase de S.

Del mismo modo, x.foo() solo debe arrojar excepciones que Base:foo() promete. No puede comenzar a lanzar nuevas excepciones inesperadas.

Si Base::foo() es público, entonces también debería ser x.foo(). De repente no puedes tener una restricción más estricta en la clase derivada, porque la clase base me prometió que era pública.

Siempre piense en la herencia como "se comporta como la superclase", o "puede tratarse como la superclase", y todo esto debe quedar claro.

+0

Gracias por su ans y especialmente por la última línea "Siempre piense en la herencia ya que" se comporta como la superclase ", o" puede tratarse como la superclase ", y todo esto debe quedar claro". – Deva

3

Punto # 2

Imagínese lo siguiente:

class Animal {} 
class Dog extends Animal {} 

class Base { 
    Dog get() { ... } 
} 

class Derived extends Base { 
    Animal get() { ... } 
} 

Base b = new Derived(); 
Dog d = b.get(); // What? 

Una lógica similar se puede aplicar a las otras preguntas.

+0

Gracias por su respuesta. Esto ya lo he mencionado en la pregunta. Lo que quería comprobar es si esta es la única razón. – Deva

+2

@Deva: ¡Esta es una razón bastante fundamental!Simplemente no tendría ningún sentido. –

+0

Yup Gracias Oli .. – Deva

1

para responder a sus puntos:

2 - ¿por qué no subclase de una superclase?

si se permitiera una superclase, esto podría suceder:

class A { 
    public A makeCopy() { return clone(); } 
} 

class B extends A { 
    public Object makeCopy() { return new Date(); } 
} 

public static void main(String[] args) { 
    A a = new B(); 
    A copy = a.makeCopy(); // OOPS -- didn't get an A after all! 
} 

3 - ¿por qué el nivel de acceso debería ser menos restrictiva?

modificar la clase B anterior a:

class B extends A { 
    private A makeCopy() { return clone(); } 
} 

public static void main(String[] args) { 
    A a = new B(); 
    A copy = a.makeCopy(); // OOPS -- accessing a private method! 
} 

4 - ¿por qué se debe lanzar una excepción estrecha?

La misma idea - si A.makeCopy se declaró a lanzar una (una clase de excepción hipotética declarada en A) AException, pero B.makeCopy se declaró a tirar Throwable, entonces B.makeCopy podría lanzar casi cualquier cosa. Eso haría imposible codificar racionalmente un bloque try/catch en main.

4

Según mi entender es sólo que si yo estoy creando un refrence clase padre para crear un objeto de clase del niño y tratando de correr por cada uno de los escenarios ...

Creo que groked la idea es correcta.

Caso con matriz de referencias clase de objeto subclase es donde las supuestas Liskov substitution principle entra en juego: en un programa de ordenador, si S es un subtipo de T, entonces los objetos de tipo T [ese es su "clase padre"] puede ser reemplazado con objetos de tipo S [ese es su "objeto de clase infantil"] (es decir, los objetos de tipo S pueden ser sustitutos de objetos de tipo T), sin alterar ninguna de las propiedades deseables de ese programa (corrección, tarea realizado, etc.) ...

+1

+1 por mencionar el principio de sustitución de Liskov – Andrey