web-dev-qa-db-fra.com

Java peut-il appeler la méthode parent substituée dans d'autres objets mais pas dans le sous-type?

ici fonctionne le code Java

class Cup {
    public String sayColor() {
        return "i have a color .";
    }
}

class TCup extends Cup{
    public String sayColor(){
        System.out.println(super.getClass().getName());
        return super.sayColor()+"color is tee green.";
    }
}

class MyTCup extends TCup {
    public String sayColor(){
        System.out.println(super.getClass().getName());
        return super.sayColor()+"but brushed to red now!";
    }
}
class Test {
    public static void main(String[] args) {
        Cup c = new MyTCup();
        System.out.print(c.sayColor());
    }
}

et exécuter les impressions de la classe Test

MyTCup
MyTCup
i have a color .color is tee green.but brushed to red now!

question 1: Au moment de l'exécution, le type d'objet C est MyTCup, mais il peut toujours appeler la super-méthode. le code ?

question 2: Il n’existe aucun moyen d’appeler la super méthode dans d’autres objets .Comme je le sais, c ++ peut appeler à tout moment la méthode parente.

35
sting

Vous ne pouvez pas appeler la super méthode dans d'autres objets - cela violerait l'encapsulation. Le but principal est que l'objet contrôle ce que font ses méthodes surchargées. Par exemple, vous pouvez redéfinir la méthode add d'une collection pour générer une exception dans certaines circonstances, de sorte que seuls les éléments "valides" soient ajoutés à la collection. Ce serait inutile si les appelants pouvaient simplement le contourner avec un casting!

La seule raison pour laquelle un objet appelle super.foo() pour lui-même est d'activer l'implémentation d'un appel à l'aide de l'implémentation parent. Il appartient au code de la classe de s’assurer qu’il ne le fait jamais que de façon sensée. Encore une fois, pour prendre l'exemple de add-in-a-collection, si la collection remplace add, elle devrait avoir la méthode un peu d'ajouter l'élément validé à la collection, ce qui serait le cas avec super.add().

Notez que pour la même raison d’encapuslation, vous pouvez seulement appeler votre implémentation parent, et non l’implémentation des grands-parents - donc super.foo() est valide, mais super.super.foo() ne l’est pas.

68
Jon Skeet

1:

Votre question n'est pas très claire. Qu'entendez-vous par "appeler au moment de l'exécution comme le code"? Si vous demandez comment l'instance c sait quelle est sa super classe, alors oui, la hiérarchie de classe est stockée en mémoire et la machine virtuelle peut y accéder.

2:

Java vous permet effectivement de convertir une instance en parent. C'est juste que l'appel d'une méthode sur une instance utilise toujours la classe réelle de l'instance, pas sa classe à la compilation. C'est à dire. en Java, toutes les méthodes sont ce que l’on appellera "virtuel" en C++. Pourquoi cela a été décidé, je ne sais pas.

Edit: En fait, Jon Skeet explique très bien pourquoi vous ne pouvez pas appeler une méthode d'une super classe sur une instance d'une sous-classe, alors je sais maintenant :-).

1
sleske

En fait, vous le pouvez, mais vous devez utiliser une méthodologie afin que cela ne fonctionne que sur votre code.
A la super classe, ajoutez le paramètre "Class" à la méthode, comme dans: 

public String sayColor(Class classFilter){...

maintenant, à chaque remplacement, vous vérifiez si la sous-classe actuelle est celle du filtre spécifié comme:

if(TCup.class!=classFilter)return super.sayColor(classFilter);
return "some text for TCup only";

J'ai codé de manière exclusive. Vous pouvez ajouter plus de paramètres, ou comparer avec null, pour pouvoir joindre les résultats aux super classes, utilisez votre créativité :)

0
Aquarius Power

Vous pouvez définir une nouvelle méthode d'assistance dans la sous-classe afin de ne pas remplacer la méthode d'origine - appelez-la -, elle peut appeler la méthode super ou non, en fonction de vos souhaits.

0
rogerdpack