417 votes

Pourquoi est-super.super.method() ; pas autorisé en Java ?

J'ai lu cette question et de la pensée qui pourrait facilement être résolu (pas qu'il n'est pas possible 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 il n'est pas, et si quelque chose comme cela existe dans d'autres langues.

Qu'avez-vous pensez?

EDIT: Pour clarifier les choses: oui, je sais, c'est impossible en Java et je n'ai pas vraiment le manquer. Ce n'est rien, j'attend de travail et a été surpris de voir arriver une erreur du compilateur. J'ai juste eu l'idée et, comme pour en discuter.

533voto

Jon Skeet Points 692016

Il viole l'encapsulation. Vous ne devriez pas être en mesure de contourner le parent de la classe de comportement. Il est logique de parfois être en mesure de contourner votre propre classe de comportement (en particulier à partir de l'intérieur de la même méthode), mais pas celle de vos parents. Par exemple, supposons que nous avons une base de "collection", une sous-classe qui représente "une collection de rouges éléments" et une sous-classe de représenter "une collection de big red". Il est logique d'avoir:

public class Items
{
    public void add(Item item) { ... }
}

public class RedItems extends Items
{
    @Override
    public void add(Item item)
    {
        if (!item.isRed())
        {
            throw new NotRedItemException();
        }
        super.add(item);
    }
}

public class BigRedItems extends RedItems
{
    @Override
    public void add(Item item)
    {
        if (!item.isBig())
        {
            throw new NotBigItemException();
        }
        super.add(item);
    }
}

C'est très bien - RedItems pouvez toujours être sûr que les éléments qu'il contient sont toutes rouges. Maintenant, supposons que nous avons été en mesure d'appeler super.super.add():

public class NaughtyItems extends RedItems
{
    @Override
    public void add(Item item)
    {
        // I don't care if it's red or not. Take that, RedItems!
        super.super.add(item);
    }
}

Maintenant, nous pourrions ajouter ce que l'on aime, et l'invariant en RedItems est cassé.

Cela fait-il sens?

88voto

Michael Myers Points 82361

Je pense que Jon Skeet a la réponse correcte. Je voudrais juste ajouter que vous pouvez accéder à l'ombre des variables à partir des super-classes de super-classes par coulée this:

interface I { int x = 0; }
class T1 implements I { int x = 1; }
class T2 extends T1 { int x = 2; }
class T3 extends T2 {
        int x = 3;
        void test() {
                System.out.println("x=\t\t"+x);
                System.out.println("super.x=\t\t"+super.x);
                System.out.println("((T2)this).x=\t"+((T2)this).x);
                System.out.println("((T1)this).x=\t"+((T1)this).x);
                System.out.println("((I)this).x=\t"+((I)this).x);
        }
}

class Test {
        public static void main(String[] args) {
                new T3().test();
        }
}

qui produit la sortie:

x= 3
super.x= 2
((T2)).x= 2
((T1)).x= 1
(I)cette).x= 0

(exemple de la JLS)

Toutefois, cela ne fonctionne pas pour les appels de méthode parce que les appels de méthode sont déterminés sur la base du runtime type de l'objet.

47voto

Nico Points 231

Je pense que ce qui suit code permettent d’utiliser les super.super...super.method() dans la plupart des cas. (même si c’est uggly de le faire)

Utilisation :

12voto

EllaJo Points 157

Je n'ai pas assez de réputation pour commentaire, donc je vais l'ajouter à l'autre des réponses.

Jon Skeet répond parfaitement, avec un bel exemple. Matt B a un point: tous les super-classes ont figurants. Votre code peut se briser si vous avez appelé un super de super qui n'avait pas super.

La programmation orientée objet (Java est) est l'ensemble des objets, des fonctions pas. Si vous souhaitez que la tâche de la programmation orientée, choisissez C++ ou autre chose. Si votre objet ne rentre pas dans c'est super classe, vous devez l'ajouter à la "grand-parent de la classe", créer une nouvelle classe, ou de trouver un autre super, il fait avec.

Personnellement, j'ai trouvé cette limitation à l'un de Java plus grandes forces. Code est un peu rigide par rapport à d'autres langues que j'ai utilisé, mais je sais toujours à quoi s'attendre. Cette aide avec le "simple et familier" objectif de Java. Dans mon esprit, un appel à super.super n'est pas simple et familier. Peut-être que les développeurs ont la même?

10voto

Larry Watanabe Points 7305

Il ya quelques bonnes raisons pour cela. Vous pourriez avoir une sous-classe qui a une méthode qui est mis en œuvre de manière incorrecte, mais la méthode parent est correctement mis en œuvre. Car il appartient à un tiers de la bibliothèque, vous risquez de ne pas/ne veulent pas modifier la source. Dans ce cas, vous souhaitez créer une sous-classe, mais remplacer une méthode à appeler le super.super méthode.

Comme indiqué par d'autres affiches, il est possible de le faire par le biais de la réflexion, mais il devrait être possible de faire quelque chose comme

(SuperSuperClass ce).theMethod();

Je fais face à ce problème dès maintenant - la solution est de copier et de coller à la super-classe de la méthode dans le subsubclass méthode :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X