Leí esta pregunta y pensé que se resolvería fácilmente (no es que no se pueda resolver sin ella) si se pudiera escribir:
@Override
public String toString() {
return super.super.toString();
}
No estoy seguro de si es útil en muchos casos, pero me pregunto por qué no lo es y si existe algo así en otros idiomas.
¿Qué piensan ustedes?
EDITAR: Para aclarar: sí, lo sé, eso es imposible en Java y realmente no lo extraño. Esto no es nada que esperaba que funcionara y me sorprendió recibir un error del compilador. Acabo de tener la idea y me gusta discutirla.
java
superclass
Tim Büthe
fuente
fuente
super.super.toString()
contradice su propia decisión cuando elige extender una clase y, por lo tanto, acepta todas (no algunas) sus características.Respuestas:
Viola la encapsulación. No debería poder evitar el comportamiento de la clase principal. A veces tiene sentido poder omitir el comportamiento de su propia clase (particularmente desde el mismo método) pero no el de sus padres. Por ejemplo, supongamos que tenemos una "colección de artículos" base, una subclase que representa "una colección de artículos rojos" y una subclase de esa que representa "una colección de artículos rojos grandes". Tiene sentido tener:
Está bien: RedItems siempre puede estar seguro de que los elementos que contiene son todos rojos. Ahora supongamos que éramos capaces de llamar super.super.add ():
Ahora podríamos agregar lo que queramos, y la invariante
RedItems
está rota.¿Tiene sentido?
fuente
Creo que Jon Skeet tiene la respuesta correcta. Solo me gustaría agregar que puede acceder a las variables sombreadas de las superclases de las superclases al emitir
this
:que produce la salida:
(ejemplo del JLS )
Sin embargo, esto no funciona para las llamadas a métodos porque las llamadas a métodos se determinan en función del tipo de tiempo de ejecución del objeto.
fuente
Creo que el siguiente código permite usar super.super ... super.method () en la mayoría de los casos. (incluso si es feo hacer eso)
En breve
Uso:
fuente
super.super.
invita a los programadores a encontrar formas nuevas, enrevesadas y atroces de dispararse en el pie en busca de una solución alternativa, este es un ejemplo perfecto de eso, porque sus colegas probablemente lo odiarán tanto por escribir algo de esta manera, te dispararán personal y literalmente en el pie. +1No tengo suficiente reputación para comentar, así que agregaré esto a las otras respuestas.
Jon Skeet responde excelentemente, con un hermoso ejemplo. Matt B tiene un punto: no todas las superclases tienen supers. Su código se rompería si llamara a un super de un super que no tenía super.
La programación orientada a objetos (que es Java) se trata de objetos, no de funciones. Si desea una programación orientada a tareas, elija C ++ u otra cosa. Si su objeto no encaja en su superclase, entonces debe agregarlo a la "clase de abuelo", crear una nueva clase o encontrar otro súper en el que encaje.
Personalmente, he encontrado que esta limitación es una de las mayores fortalezas de Java. El código es algo rígido en comparación con otros idiomas que he usado, pero siempre sé qué esperar. Esto ayuda con el objetivo "simple y familiar" de Java. En mi opinión, llamar a super.super no es simple ni familiar. ¿Quizás los desarrolladores sintieron lo mismo?
fuente
Hay algunas buenas razones para hacer esto. Es posible que tenga una subclase que tiene un método que se implementa incorrectamente, pero el método principal se implementa correctamente. Debido a que pertenece a una biblioteca de terceros, es posible que no pueda / no quiera cambiar la fuente. En este caso, desea crear una subclase pero anular un método para llamar al método super.super.
Como se muestra en algunos otros carteles, es posible hacer esto a través de la reflexión, pero debería ser posible hacer algo como
(SuperSuperClass this) .theMethod ();
Estoy lidiando con este problema en este momento: la solución rápida es copiar y pegar el método de superclase en el método de subclase :)
fuente
Además de los muy buenos puntos que otros han hecho, creo que hay otra razón: ¿qué pasa si la superclase no tiene una superclase?
Como cada clase se extiende naturalmente (al menos)
Object
,super.whatever()
siempre se referirá a un método en la superclase. Pero lo que si su clase sólo se extiendeObject
- lo quesuper.super
se refieren a continuación? ¿Cómo debe manejarse ese comportamiento: un error del compilador, un puntero nulo, etc.?Creo que la razón principal por la que esto no está permitido es que viola la encapsulación, pero esta podría ser una pequeña razón también.
fuente
Creo que si sobrescribe un método y desea toda la versión de
equals
superclase del mismo (como, por ejemplo ), entonces virtualmente siempre querrá llamar primero a la versión de superclase directa, que a su vez llamará a su versión de superclase si así lo desea .Creo que rara vez tiene sentido (si es que no. No puedo pensar en un caso en el que lo haga) llamar a una versión arbitraria de una superclase de un método. No sé si eso es posible en Java. Se puede hacer en C ++:
fuente
Supongo que porque no se usa con tanta frecuencia. La única razón por la que pude ver su uso es si su padre directo ha anulado alguna funcionalidad y está tratando de restaurarlo al original.
Lo que me parece estar en contra de los principios OO, ya que el padre directo de la clase debería estar más estrechamente relacionado con su clase que el abuelo.
fuente
Mire este proyecto de Github, especialmente la variable objectHandle. Este proyecto muestra cómo llamar de manera real y precisa al método de abuelo en un nieto.
En caso de que el enlace se rompa, aquí está el código:
Feliz codificación !!!!
fuente
Pondría el cuerpo del método super.super en otro método, si es posible
O si no puede cambiar la super-super clase, puede intentar esto:
En ambos casos, el
resultados para "Soy super super"
fuente
Parecería posible obtener al menos la clase de la superclase de la superclase, aunque no necesariamente la instancia de la misma, utilizando la reflexión; Si esto puede ser útil, considere el Javadoc en http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass ()
fuente
ejecutar: UNA CREACIÓN EXITOSA (tiempo total: 0 segundos)
fuente
Llamar a super.super.method () tiene sentido cuando no puede cambiar el código de la clase base. Esto sucede a menudo cuando está extendiendo una biblioteca existente.
Pregúntese primero, ¿por qué está extendiendo esa clase? Si la respuesta es "porque no puedo cambiarlo", puede crear un paquete y una clase exactos en su aplicación, y reescribir un método travieso o crear un delegado:
Por ejemplo, puede crear la clase org.springframework.test.context.junit4.SpringJUnit4ClassRunner en su aplicación para que esta clase se cargue antes que la real desde jar. Luego reescribe métodos o constructores.
Atención: este es un truco absoluto, y NO se recomienda su uso, ¡pero FUNCIONA! El uso de este enfoque es peligroso debido a posibles problemas con los cargadores de clases. Además, esto puede causar problemas cada vez que actualice la biblioteca que contiene una clase sobrescrita.
fuente
He tenido situaciones como estas cuando la arquitectura es crear una funcionalidad común en una CustomBaseClass común que implementa en nombre de varias clases derivadas. Sin embargo, debemos evitar la lógica común para un método específico para una clase derivada específica. En tales casos, debemos usar una implementación super.super.methodX.
Logramos esto mediante la introducción de un miembro booleano en CustomBaseClass, que se puede usar para diferir selectivamente la implementación personalizada y ceder a la implementación de marco predeterminada cuando sea deseable.
Sin embargo, con buenos principios de arquitectura seguidos tanto en el marco como en la aplicación, podríamos evitar tales situaciones fácilmente, usando el enfoque hasA, en lugar del enfoque isA. Pero en todo momento no es muy práctico esperar una arquitectura bien diseñada y, por lo tanto, la necesidad de alejarse de principios de diseño sólidos e introducir hacks como este. Solo mis 2 centavos ...
fuente
@ Jon Skeet Buena explicación. En mi opinión, si alguien quiere llamar al método super.super, entonces uno debe querer ignorar el comportamiento del padre inmediato, pero quiere acceder al comportamiento del padre principal. Esto se puede lograr a través de la instancia de. Como abajo código
Aquí está la clase de conductor,
La salida de esto será
El comportamiento de clase B printClass se ignorará en este caso. No estoy seguro de si es una práctica ideal o buena para lograr super.super, pero aún funciona.
fuente
Si cree que va a necesitar la superclase, puede hacer referencia a ella en una variable para esa clase. Por ejemplo:
Debe imprimir:
fuente
new UltraFoo.getNumber()
no compilaré, ya que te perdiste los paréntesis. Sin embargo, acabo de eliminar mi donvote, ya que el concepto de su código es bastante claro ahora, ¡gracias!En mi opinión, es una forma limpia de lograr un
super.super.sayYourName()
comportamiento en Java.Salida:
Request to lie: d.sayYourName(true) returns Grandma Fedora
Request not to lie: d.sayYourName(false) returns Little girl Masha
fuente
Creo que este es un problema que rompe el acuerdo de herencia.
Al extender una clase, obedece / acuerda su comportamiento, características
Mientras que cuando llama
super.super.method()
, quiere romper su propio acuerdo de obediencia.Simplemente no puedes elegir entre la súper clase .
Sin embargo, pueden ocurrir situaciones en las que sienta la necesidad de llamar
super.super.method()
, ¡generalmente un signo de diseño incorrecto, en su código o en el código que hereda!Si las clases super y super super no se pueden refactorizar (algún código heredado), entonces opte por la composición sobre la herencia.
La ruptura de la encapsulación se produce cuando se omiten algunos métodos rompiendo el código encapsulado. Los métodos diseñados para no ser anulados se marcan como finales .
fuente
En C # puede llamar a un método de cualquier antepasado como este:
También puedes hacer esto en Delphi:
Pero en Java puedes hacer ese enfoque solo con algún equipo. Una forma posible es:
Resultado del resultado objC.DoIt ():
fuente
Es simplemente fácil de hacer. Por ejemplo:
C subclase de B y B subclase de A. Ambos tienen el método methodName () por ejemplo.
Ejecutar clase C La salida será: Clase A Clase C
En lugar de salida: Clase A Clase B Clase C
fuente
Salida: Impreso en el GrandDad
fuente
super.super.method()
código no es válido en Java.La palabra clave super es solo una forma de invocar el método en la superclase. En el tutorial de Java: https://docs.oracle.com/javase/tutorial/java/IandI/super.html
Si su método anula uno de los métodos de su superclase, puede invocar el método anulado mediante el uso de la palabra clave super.
¡No creas que es una referencia del súper objeto! No, es solo una palabra clave para invocar métodos en la superclase.
Aquí hay un ejemplo:
Cuando llame
cat.doSth()
, se imprimirá el métododoSth()
en clase y es un gato.Animal
this
fuente