2011-07-14 7 views
12

Cuando anula un método, debe mantener la firma del método y no puede reducir su visibilidad. Ahora probé lo que sucede cuando hago esto con atributos. Me sorprendió - ¡FUNCIONA! Mire usted mismo:Anular atributos

public class A { 

    public Integer myAttribute; 

} 

public class B extends A { 

    public String myAttribute; 

} 

public class Main { 

     public static void main(String[] args) { 
     B b = new B(); 
     b.myAttribute = "myString"; 
     ((A) b).myAttribute = 1337; 
     System.out.println(b.myAttribute); 
     System.out.println(((A)b).myAttribute); 
    } 

} 

lo tanto, es posible escribir un atributo en una subclase con el mismo nombre attibute como en la superclase, pero se puede utilizar la visibilidad diferente (modificador) y el tipo. Entonces diría que los atributos en superclase y subclase son casi completamente independientes entre sí.

Ahora, si realmente usa el mismo nombre de atributo en superclase y subclase, efectivamente oculta el atributo de la superclase. Al acceder al atributo usando la subclase, obtienes el atributo de la subclase. ¡Pero el atributo de la superclase está allí también! Debes realizar un lanzamiento para acceder al atributo de la superclase desde afuera. Desde dentro, la palabra clave "super" debe ser útil.

Pregunta 1: Ahora, básicamente, tiene dos atributos diferentes con el mismo nombre. ¿Esto no rompe LSP?

Por qué llegué a este detalle es este: Estoy experimentando con un marco de persistencia auto escrito. Quiero leer el estado interno completo de un objeto y persistir ese estado. Leo todos los valores de los atributos a través de la reflexión, comenzando en el subtipo y atravesando las superclases. Ahora, si hay dos atributos con el mismo nombre en superclase y subclase, debo recordar la clase que declara que un atributo puede asignar los valores de los atributos a los atributos correctos y restaurar el estado de un objeto.

Pregunta 2: ¿Alguna otra idea sobre cómo lidiar con este detalle? Pregunta 3: ¿Cómo manejan otros marcos de persistencia este detalle?

Nunca vi este detalle en uso. Tal vez escribir dos atributos con el mismo nombre es un poco feo, pero es posible y cualquier marco de persistencia puede enfrentarse a él. Tal vez haya situaciones en las que esta técnica pueda ser útil.

Thans por adelantado.

+0

Gracias a todos los que responden. – anonymous

Respuesta

5

ORM usualmente usan el estándar javabeans que define "propiedades". Las propiedades se definen mediante un método de lector y/o escritor en lugar del campo que leen/escriben. En el 99% de los casos, las propiedades son field + getter & setter, pero no tiene que ser el caso. Y el ORM lee estas propiedades y solo detecta los campos que tienen getters & setters. Dado que los métodos se anulan en lugar de sombrearse, el problema ya no existe.

Esto es más un problema de encapsulación que una violación de LSP. El acceso al campo no se ve afectado por el polimorfismo, por lo que si tiene Foo foo = new FooSubclas(); foo.field the value of the se tomará el campo Foo`, lo que significa que el comportamiento no cambiará.

+0

No me gusta estar obligado a la especificación de frijoles debido a sus restricciones. Esa es una de las razones por las que decidí probar mi propio marco de persistencia. Ahora enfrento algunos de los problemas que otras implementaciones evitaron solo con frijoles persistentes. Creo que solo tengo que extender mi metamodelo para representar la herencia de forma más correcta. – anonymous

2

Pregunta 1: No se rompe el LSP, porque las variables miembro no son polimórficas.

1

Pregunta 1: LSP es aproximadamente behavioral subtyping y yo diría que tener dos miembros con el mismo nombre no cambia el comportamiento.

Pregunta 2: Detectélo (de todos modos necesitaría escanear la jerarquía de clases) y no lo permita.

1

Pregunta 2: Solo serialize/deserialize a través de getters/setters.

Pregunta 3: Véase la respuesta 2.

1

No se puede reemplazar un atributo, solamente ocultarlo. Esto es literalmente llamado ocultar campos en el tutorial. Más detalles sobre este blog.

Q1: No, no se rompe LSP, cualquier referencia a A a = new B(); a.myAttribute seguirá haciendo referencia a A.myAttribute y no a B.myAttribute.

Q2: Intentaré evitarlo, pero si debe hacerlo, aún puede acceder al A.myAttribute desde B utilizando la palabra clave super.myAttribute.

Q3: Creo que C# permite lo mismo, usan base en lugar de super, pero no tengo ningún compilador de C# a la mano, y la documentación sobre el campo oculto en C# es escasa.

Cuestiones relacionadas