public class SuperClass
{
public void method1()
{
System.out.println("superclass method1");
this.method2();
}
public void method2()
{
System.out.println("superclass method2");
}
}
public class SubClass extends SuperClass
{
@Override
public void method1()
{
System.out.println("subclass method1");
super.method1();
}
@Override
public void method2()
{
System.out.println("subclass method2");
}
}
public class Demo
{
public static void main(String[] args)
{
SubClass mSubClass = new SubClass();
mSubClass.method1();
}
}
ma sortie attendue:
sous-classe méthode1
superclasse méthode1
superclasse méthode2
sortie réelle:
sous-classe méthode1
superclasse méthode1
sous-classe méthode2
Je sais techniquement que j'ai remplacé une méthode publique, mais j'ai pensé que parce que j'appelais le super, tous les appels dans le super resteraient dans le super, cela ne se produit pas. Des idées sur la façon dont je peux y arriver?
java
inheritance
overriding
super
jsonfry
la source
la source
Réponses:
Le mot
super
- clé ne "colle" pas. Chaque appel de méthode est géré individuellement, donc même si vous y parvenezSuperClass.method1()
en appelantsuper
, cela n'influence aucun autre appel de méthode que vous pourriez faire à l'avenir.Cela signifie qu'il n'y a pas de moyen direct d'appeler
SuperClass.method2()
depuisSuperClass.method1()
sans y aller,SubClass.method2()
sauf si vous travaillez avec une instance réelle deSuperClass
.Vous ne pouvez même pas obtenir l'effet souhaité en utilisant Reflection (voir la documentation de
java.lang.reflect.Method.invoke(Object, Object...)
).[EDIT] Il semble encore y avoir une certaine confusion. Laissez-moi essayer une explication différente.
Lorsque vous invoquez
foo()
, vous invoquez en faitthis.foo()
. Java vous permet simplement d'omettre le fichierthis
. Dans l'exemple de la question, le type dethis
estSubClass
.Ainsi, lorsque Java exécute le code
SuperClass.method1()
, il arrive finalement àthis.method2();
L'utilisation
super
ne change pas l'instance pointée parthis
. Donc l'appel va àSubClass.method2()
puisquethis
est de typeSubClass
.Peut-être que c'est plus facile à comprendre quand on imagine que Java passe
this
comme un premier paramètre caché:Si vous suivez la pile d'appels, vous pouvez voir que cela
this
ne change jamais, c'est toujours l'instance créée dansmain()
.la source
super
. Chaque fois qu'il appelle une méthode, il examine le type d'instance et commence à rechercher la méthode avec ce type, quelle que soit la fréquence de l'appelsuper
. Ainsi, lorsque vous appelezmethod2
une instance deSubClass
, elle verra toujours celle duSubClass
premier.super
ne change pas l'instance. Il ne définit pas de champ caché "à partir de maintenant, tous les appels de méthode devraient commencer à utiliserSuperClass
". Ou pour le dire autrement: la valeur dethis
ne change pas.Vous ne pouvez accéder aux méthodes remplacées que dans les méthodes de substitution (ou dans d'autres méthodes de la classe de substitution).
Donc: ne remplacez pas
method2()
ou appelezsuper.method2()
dans la version remplacée.la source
Vous utilisez le
this
mot - clé qui fait référence à "l'instance en cours d'exécution de l'objet que vous utilisez", c'est-à-dire que vous invoquezthis.method2();
sur votre superclasse, c'est-à-dire qu'il appellera la méthode2 () sur l'objet que vous ' re using, qui est la sous-classe.la source
this
n'aidera pas non plus. Une invocation non qualifiée utilise implicitementthis
method2()
le compilateur verrathis.method2()
. Donc, même si vous supprimez le,this
cela ne fonctionnera toujours pas. Ce que @Sean Patrick Floyd dit est correctthis
this
réfère à la "classe d'instance en cours d'exécution concrète" (connue à l'exécution) et non (comme l'affiche semble le croire) à la "classe d'unité de compilation actuelle" (où le mot-clé est utilisé, connu dans temps de compilation). Mais cela peut aussi être trompeur (comme le souligne Shervin):this
est également référencé implicitement avec l'appel de méthode simple;method2();
est le même quethis.method2();
J'y pense de cette façon
Permettez-moi de déplacer cette sous-classe un peu vers la gauche pour révéler ce qui se trouve en dessous ... (Mec, j'adore les graphiques ASCII)
En d'autres termes, citant la spécification du langage Java :
En termes simples,
this
est essentiellement un objet (* l'objet **; le même objet que vous pouvez déplacer dans les variables), l'instance de la classe instanciée, une simple variable dans le domaine des données;super
est comme un pointeur vers un bloc de code emprunté que vous souhaitez exécuter, plus comme un simple appel de fonction, et il est relatif à la classe où il est appelé.Par conséquent, si vous utilisez à
super
partir de la superclasse, vous obtenez le code de la superduper classe [le grand-parent] exécuté), tandis que si vous utilisezthis
(ou si elle est utilisée implicitement) d'une superclasse, il continue de pointer vers la sous-classe (car personne ne l'a changé - et personne pourrait).la source
Si vous ne voulez pas que superClass.method1 appelle subClass.method2, rendez la méthode2 privée afin qu'elle ne puisse pas être remplacée.
Voici une suggestion:
Si cela ne fonctionnait pas de cette façon, le polymorphisme serait impossible (ou du moins même pas à moitié aussi utile).
la source
Puisque le seul moyen d'éviter qu'une méthode soit remplacée est d'utiliser le mot - clé super , j'ai pensé à déplacer la méthode2 () de SuperClass vers une autre nouvelle classe de base , puis à l'appeler depuis SuperClass :
Production:
la source
this
fait toujours référence à l'objet en cours d'exécution.Pour illustrer davantage ce point, voici une simple esquisse:
Si vous avez une instance de la boîte extérieure, un
Subclass
objet, partout où vous vous aventurez à l'intérieur de la boîte, même dans laSuperclass
«zone», c'est toujours l'instance de la boîte extérieure.De plus, dans ce programme, il n'y a qu'un seul objet qui est créé à partir des trois classes, donc
this
ne peut jamais faire référence à une chose et c'est:comme indiqué dans le «Heap Walker» de Netbeans .
la source
appel
les sorties
la source
Je ne pense pas que vous puissiez le faire directement. Une solution de contournement serait d'avoir une implémentation interne privée de method2 dans la superclasse et de l'appeler. Par exemple:
la source
«this» mot-clé fait référence à la référence de classe actuelle. Cela signifie que lorsqu'elle est utilisée dans la méthode, la classe 'courante' est toujours SubClass et donc, la réponse est expliquée.
la source
Pour résumer, cela pointe vers l'objet actuel et l'invocation de la méthode en java est polymorphe par nature. Ainsi, la sélection de la méthode pour l'exécution dépend totalement de l'objet pointé par ceci. Par conséquent, l'appel de la méthode method2 () à partir de la classe parent invoque method2 () de la classe enfant, car this pointe vers l'objet de la classe enfant. La définition de ceci ne change pas, quelle que soit la classe utilisée.
PS. contrairement aux méthodes, les variables membres de classe ne sont pas polymorphes.
la source
Au cours de mes recherches pour un cas similaire, j'ai fini par vérifier la trace de la pile dans la méthode de sous-classe pour savoir d'où vient l'appel. Il existe probablement des moyens plus intelligents de le faire, mais cela fonctionne pour moi et c'est une approche dynamique.
Je pense que la question d'avoir une solution pour le cas est raisonnable. Il existe bien sûr des moyens de résoudre le problème avec différents noms de méthode ou même différents types de paramètres, comme déjà mentionné dans le fil de discussion, mais dans mon cas, je n'aime pas confondre avec différents noms de méthode.
la source
Plus étendu la sortie de la question soulevée, cela donnera plus d'informations sur le spécificateur d'accès et le comportement de remplacement.
la source