J'ai lu cette question et j'ai pensé que cela serait facilement résolu (pas qu'il ne soit pas résolu sans) si l'on pouvait écrire:
@Override
public String toString() {
return super.super.toString();
}
Je ne sais pas si c'est utile dans de nombreux cas, mais je me demande pourquoi ce n'est pas le cas et si quelque chose comme ça existe dans d'autres langues.
Qu'en pensez-vous?
EDIT: Pour clarifier: oui je sais, c'est impossible en Java et ça ne me manque pas vraiment. Ce n'est rien que je m'attendais à travailler et j'ai été surpris d'obtenir une erreur de compilation. J'ai juste eu l'idée et j'aimerais en discuter.
java
superclass
Tim Büthe
la source
la source
super.super.toString()
contredit votre propre décision lorsque vous choisissez d'étendre une classe, acceptant ainsi toutes (pas certaines) ses fonctionnalités.Réponses:
Il viole l'encapsulation. Vous ne devriez pas pouvoir contourner le comportement de la classe parent. Il est logique de pouvoir parfois contourner le comportement de votre propre classe (en particulier à partir de la même méthode) mais pas celui de vos parents. Par exemple, supposons que nous ayons une base "collection d'articles", une sous-classe représentant "une collection d'articles rouges" et une sous-classe de celle représentant "une collection de gros articles rouges". Il est logique d'avoir:
C'est bien - RedItems peut toujours être sûr que les éléments qu'il contient sont tous rouges. Supposons maintenant que nous avons été en mesure d'appeler super.super.add ():
Maintenant, nous pourrions ajouter tout ce que nous voulons, et l'invariant dans
RedItems
est rompu.Cela a-t-il du sens?
la source
Je pense que Jon Skeet a la bonne réponse. Je voudrais juste ajouter que vous pouvez accéder aux variables ombrées à partir de superclasses de superclasses en transtypant
this
:qui produit la sortie:
(exemple du JLS )
Cependant, cela ne fonctionne pas pour les appels de méthode, car les appels de méthode sont déterminés en fonction du type d'exécution de l'objet.
la source
Je pense que le code suivant permet d'utiliser super.super ... super.method () dans la plupart des cas. (même si c'est moche de faire ça)
En bref
Utilisation:
la source
super.super.
invite les programmeurs à trouver de nouvelles façons compliquées et flagrantes de se tirer une balle dans le pied dans la poursuite d'une solution de contournement, ceci en est un parfait exemple, car vos collègues vous détesteront probablement tellement pour avoir écrit quelque chose comme ça, ils vous tireront personnellement et littéralement dans le pied. +1Je n'ai pas assez de réputation pour commenter, je vais donc l'ajouter aux autres réponses.
Jon Skeet répond parfaitement, avec un bel exemple. Matt B a raison: toutes les superclasses n'ont pas de supers. Votre code se briserait si vous appeliez un super d'un super qui n'avait pas de super.
La programmation orientée objet (qui est Java) concerne les objets, pas les fonctions. Si vous voulez une programmation orientée tâche, choisissez C ++ ou autre chose. Si votre objet ne rentre pas dans sa super classe, vous devez l'ajouter à la "classe des grands-parents", créer une nouvelle classe ou trouver un autre super auquel il rentre.
Personnellement, j'ai trouvé cette limitation comme l'une des plus grandes forces de Java. Le code est quelque peu rigide par rapport aux autres langages que j'ai utilisés, mais je sais toujours à quoi m'attendre. Cela contribue à l'objectif "simple et familier" de Java. Dans mon esprit, appeler super.super n'est ni simple ni familier. Peut-être que les développeurs ont ressenti la même chose?
la source
Il y a de bonnes raisons de le faire. Vous pouvez avoir une sous-classe qui a une méthode qui n'est pas implémentée correctement, mais la méthode parent est implémentée correctement. Parce qu'elle appartient à une bibliothèque tierce, vous pourriez ne pas pouvoir / ne pas vouloir changer la source. Dans ce cas, vous souhaitez créer une sous-classe mais remplacer une méthode pour appeler la méthode super.super.
Comme le montrent certaines autres affiches, il est possible de le faire par la réflexion, mais il devrait être possible de faire quelque chose comme
(SuperSuperClass this) .theMethod ();
Je traite ce problème en ce moment - la solution rapide consiste à copier et coller la méthode de superclasse dans la méthode de sous-sous-classe :)
la source
En plus des très bons points que d'autres ont soulevés, je pense qu'il y a une autre raison: que faire si la superclasse n'a pas de superclasse?
Puisque chaque classe s'étend naturellement (au moins)
Object
,super.whatever()
fera toujours référence à une méthode dans la superclasse. Mais que se passe-t-il si votre classe ne fait que s'étendreObject
- à quoi sesuper.super
référer alors? Comment ce comportement doit-il être géré - une erreur de compilation, un NullPointer, etc.?Je pense que la principale raison pour laquelle cela n'est pas autorisé est qu'il viole l'encapsulation, mais cela pourrait aussi être une petite raison.
la source
Je pense que si vous écrasez une méthode et que vous voulez toute la version super-classe de celle-ci (comme, disons pour
equals
), alors vous voulez presque toujours appeler la version directe de la superclasse en premier, que l'on appellera sa version de superclasse à son tour si elle le veut .Je pense que cela n'a que rarement de sens (voire pas du tout. Je ne peux pas penser à un cas où il le fait) d'appeler une version arbitraire d'une superclasse d'une méthode. Je ne sais pas si cela est possible du tout en Java. Cela peut être fait en C ++:
la source
À une supposition, parce que ce n'est pas souvent utilisé. La seule raison pour laquelle je pouvais voir l'utiliser est que votre parent direct a outrepassé certaines fonctionnalités et que vous essayez de les restaurer à leur version d'origine.
Ce qui me semble contraire aux principes OO, car le parent direct de la classe devrait être plus étroitement lié à votre classe que le grand-parent.
la source
Regardez ce projet Github, en particulier la variable objectHandle. Ce projet montre comment appeler réellement et précisément la méthode des grands-parents sur un petit-enfant.
Juste au cas où le lien serait rompu, voici le code:
Happy Coding !!!!
la source
Je mettrais le corps de la méthode super.super dans une autre méthode, si possible
Ou si vous ne pouvez pas changer la classe super-super, vous pouvez essayer ceci:
Dans les deux cas, le
résultats à "je suis super super"
la source
Il semblerait possible d'obtenir au moins la classe de la superclasse de la superclasse, mais pas nécessairement l'instance de celle-ci, en utilisant la réflexion; si cela peut être utile, veuillez considérer le Javadoc à http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass ()
la source
courir: UNE CONSTRUCTION RÉUSSIE (durée totale: 0 seconde)
la source
L'appel de super.super.method () est logique lorsque vous ne pouvez pas modifier le code de la classe de base. Cela se produit souvent lorsque vous étendez une bibliothèque existante.
Demandez-vous d'abord, pourquoi prolongez-vous cette classe? Si la réponse est "parce que je ne peux pas le changer", vous pouvez créer le package et la classe exacts dans votre application, et réécrire la méthode coquine ou créer un délégué:
Par exemple, vous pouvez créer la classe org.springframework.test.context.junit4.SpringJUnit4ClassRunner dans votre application de sorte que cette classe doit être chargée avant la vraie depuis jar. Réécrivez ensuite les méthodes ou les constructeurs.
Attention: Il s'agit d'un hack absolu, et il est fortement déconseillé d'utiliser, mais cela fonctionne! L'utilisation de cette approche est dangereuse en raison de problèmes possibles avec les chargeurs de classe. Cela peut également entraîner des problèmes à chaque fois que vous mettez à jour la bibliothèque qui contient une classe remplacée.
la source
J'ai eu des situations comme celles-ci lorsque l'architecture consiste à créer des fonctionnalités communes dans une CustomBaseClass commune qui implémente au nom de plusieurs classes dérivées. Cependant, nous devons contourner la logique commune pour une méthode spécifique pour une classe dérivée spécifique. Dans de tels cas, nous devons utiliser une implémentation super.super.methodX.
Nous y parvenons en introduisant un membre booléen dans la CustomBaseClass, qui peut être utilisé pour différer sélectivement l'implémentation personnalisée et céder le pas à l'implémentation du framework par défaut lorsque cela est souhaitable.
Cependant, avec de bons principes d'architecture suivis dans le cadre ainsi que dans l'application, nous pourrions éviter de telles situations facilement, en utilisant une approche hasA, au lieu d'une approche isA. Mais à tout moment, il n'est pas très pratique de s'attendre à une architecture bien conçue en place, et donc la nécessité de s'éloigner des principes de conception solides et d'introduire des hacks comme celui-ci. Juste mes 2 cents ...
la source
@ Jon Skeet Belle explication. IMO si quelqu'un veut appeler la méthode super.super, alors il faut vouloir ignorer le comportement du parent immédiat, mais vouloir accéder au comportement du grand parent. Ceci peut être réalisé via l'instance de. Comme ci-dessous le code
Voici la classe de pilote,
La sortie de ceci sera
Le comportement de classe B printClass sera ignoré dans ce cas. Je ne suis pas sûr que ce soit une pratique idéale ou bonne pour atteindre super.super, mais cela fonctionne toujours.
la source
Si vous pensez que vous allez avoir besoin de la superclasse, vous pouvez la référencer dans une variable pour cette classe. Par exemple:
Devrait imprimer:
la source
new UltraFoo.getNumber()
je ne compilerai pas, car vous avez manqué les parenthèses là-bas. Cependant, je viens de supprimer mon don, car le concept de votre code est assez clair maintenant, merci!IMO, c'est une façon propre de réaliser un
super.super.sayYourName()
comportement en Java.Production:
Request to lie: d.sayYourName(true) returns Grandma Fedora
Request not to lie: d.sayYourName(false) returns Little girl Masha
la source
Je pense que c'est un problème qui rompt l'accord de succession.
En étendant une classe, vous obéissez / acceptez son comportement, caractéristiques
Pendant que vous appelez
super.super.method()
, vous voulez rompre votre propre accord d'obéissance.Vous ne pouvez tout simplement pas choisir la super classe .
Cependant, il peut arriver des situations où vous ressentez le besoin d'appeler
super.super.method()
- généralement un mauvais signe de conception, dans votre code ou dans le code dont vous héritez!Si les classes super et super super ne peuvent pas être refactorisées (certains codes hérités), optez pour la composition plutôt que l'héritage.
La rupture d'encapsulation consiste à @Override certaines méthodes en cassant le code encapsulé. Les méthodes conçues pour ne pas être remplacées sont marquées comme finales .
la source
En C #, vous pouvez appeler une méthode de n'importe quel ancêtre comme ceci:
Vous pouvez également le faire dans Delphi:
Mais en Java, vous ne pouvez faire cette mise au point que par un certain équipement. Une façon possible est:
Sortie du résultat objC.DoIt ():
la source
C'est tout simplement facile à faire. Par exemple:
Sous-classe C de B et sous-classe B de A. Les deux ont par exemple la méthode methodName ().
Exécuter la classe C La sortie sera: Classe A Classe C
Au lieu de la sortie: Classe A Classe B Classe C
la source
Sortie: imprimée sur le grand-père
la source
super.super.method()
code n'est pas valide en Java.Le mot-clé super n'est qu'un moyen d'invoquer la méthode dans la superclasse. Dans le tutoriel Java: https://docs.oracle.com/javase/tutorial/java/IandI/super.html
Si votre méthode remplace l'une des méthodes de sa superclasse, vous pouvez invoquer la méthode substituée en utilisant le mot clé super.
Ne croyez pas que c'est une référence du super objet !!! Non, c'est juste un mot-clé pour invoquer des méthodes dans la superclasse.
Voici un exemple:
Lorsque vous appelez
cat.doSth()
, la méthodedoSth()
en classeAnimal
s'imprimethis
et c'est un chat.la source