109 votes

Quand NE PAS appeler la méthode super() lors d'une surcharge ?

Quand je crée ma propre classe personnalisée Android, je extend sa classe native. Ensuite, lorsque je veux surcharger la méthode de base, j'appelle toujours super() comme je le fais toujours dans onCreate , onStop etc.

Et j'ai pensé que c'était ça, car dès le début l'équipe Android nous a conseillé de toujours appeler super sur chaque surcharge de méthode.

Mais, en de nombreux livres Je constate que les développeurs, plus expérimentés que moi, omettent souvent d'appeler super et je doute vraiment qu'ils le fassent par manque de connaissances. Par exemple, regardez cette base SAX classe d'analyseur où super est omise dans startElement , characters y endElement :

public class SAXParser extends DefaultHandler{
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(qName.equalsIgnoreCase("XXY")) {
            //do something
        }
    }

    public void characters(char[] ch, int start, int length) throws SAXException {
        //do something
    }

    public void endElement(String uri, String localName, String qName) throws SAXException {
        if(qName.equalsIgnoreCase("XXY")) {
            //do something
        }else () {
            //do something
        }
    }
}

Si vous essayez de créer une méthode de remplacement via Eclipse ou tout autre IDE, super sera toujours créé dans le cadre d'un processus automatisé.

Ce n'était qu'un simple exemple. Les livres sont plein de code similaire .

Comment savent-ils quand vous devez appeler super et quand vous pouvez l'omettre en l'appelant ?

PS. Ne vous attachez pas à cet exemple spécifique. C'est juste un exemple pris au hasard parmi de nombreux exemples.

(Cela peut sembler être une question de débutant, mais je suis vraiment confus).

140voto

Xavi López Points 14801

En appelant le super méthode, vous n'êtes pas Remplacement de le comportement de la méthode, vous extension de il.

Un appel à super exécutera toute logique que la classe que vous étendez a définie pour cette méthode. Prenez en compte le fait qu'il pourrait être important au moment où vous appelez super dans l'implémentation de votre méthode de surcharge. Par exemple :

public class A { 
    public void save() { 
         // Perform save logic
    }
}

public class B extends A {
    private Object b;
    @Override
    public void save() { 
        super.save(); // Performs the save logic for A
        save(b); // Perform additional save logic
    }
}

Un appel à B.save() effectuera le save() logique pour les deux A y B dans cet ordre particulier. Si tu n'appelais pas super.save() à l'intérieur de B.save() , A.save() ne serait pas appelé. Et si vous avez appelé super.save() après save(b) , A.save() serait effectivement réalisée après B.save() .

Si vous voulez contourner super (c'est-à-dire ignorer complètement son implémentation et la fournir vous-même), vous ne devriez pas appeler super .

Dans le SAXParser exemple que vous fournissez, le mises en œuvre de DefaultHandler pour ces méthodes sont simplement vides, afin que les sous-classes puissent les surcharger et fournir un comportement pour ces méthodes. Dans les javadoc pour cette méthode, cela est également souligné.

public void startElement (String uri, String localName,
    String qName, Attributes attributes) throws SAXException {
    // no op
}

A propos de la super() appel par défaut dans le code généré par les IDE, en tant que @barsju a souligné dans son commentaire, dans chaque constructeur il y a un appel implicite à super() (même si vous ne l'écrivez pas dans votre code), ce qui signifie, dans ce contexte, qu'un appel à super Le constructeur par défaut de l'utilisateur. Le site IDE l'écrit simplement pour vous, mais il sera également appelé si vous le supprimez. Remarquez également que lors de l'implémentation des constructeurs, super() ou l'une de ses variantes avec des arguments (c'est-à-dire super(x,y,z) ) ne peut être appelé que au tout début de la méthode.

16voto

yorkw Points 24676

Comment savent-ils quand vous devez appeler le super et quand vous pouvez omettre de l'appeler ?

En général, si une méthode spéciale de l'API a une signification critique pour le cycle de vie du contexte du cadre sous-jacent, elle sera toujours explicitement mentionnée et mise en évidence dans la documentation de l'API, comme la méthode Activity.onCreate() Documentation de l'API . De plus, si l'API est conçue de manière robuste, elle devrait lever certaines exceptions pour alerter le développeur du consommateur au moment de la compilation du projet et s'assurer qu'elle ne génère pas de faute au moment de l'exécution.

Si cela n'est pas explicitement indiqué dans la documentation de l'API, le développeur du consommateur peut supposer sans risque que l'appel de la méthode de l'API n'est pas obligatoire lorsqu'il la surcharge. C'est au développeur du consommateur de décider s'il doit utiliser le comportement par défaut (appeler la méthode de l super ) ou la remplacer complètement.

Si la condition est autorisée (j'adore les logiciels libres), le développeur consommateur peut toujours consulter le code source de l'API et voir comment la méthode est réellement écrite sous le capot. Consultez Activity.onCreate() source y DefaultHandler.startElement() source par exemple.

7voto

Michael Points 776

Le test que vous devez faire dans votre tête est le suivant :

"Est-ce que je veux que toutes les fonctionnalités de cette méthode soient faites pour moi, puis faire quelque chose après ?" Si oui, alors vous voulez appeler super() puis terminez votre méthode. Cela sera vrai pour les méthodes "importantes" telles que onDraw() qui gère beaucoup de choses en arrière-plan.

Si vous ne voulez qu'une partie de la fonctionnalité (comme c'est le cas pour la plupart des méthodes que vous allez surcharger), vous ne voulez probablement pas appeler super() .

3voto

ngesh Points 8686

Bien Xavi a donné une meilleure réponse mais vous devez probablement savoir ce que fait super() fait quand il est appelé dans une méthode surchargée ... il annonce ce que vous avez fait avec le comportement par défaut ...

par exemple

onDraw() 

dans la classe de vue quand elle est surchargée vous dessinez quelque chose avant de dire super.onDraw() il apparaît une fois que la vue est entièrement dessinée donc ici appeler super est nécessaire car Android a des choses très importantes à faire (comme onCreate()).

mais en même temps

onLongClick()

Quand vous remplacez cette méthode, vous ne voulez pas appeler super parce que cela fait apparaître une boîte de dialogue avec une liste d'options pour un EditText ou toute autre vue similaire C'est la différence de base vous avez le choix de le laisser parfois mais pour les autres méthodes comme onCreate() , onStop() vous devriez laisser le système d'exploitation s'en occuper

2voto

Vikas Gupta Points 890

Je n'ai pas bien compris votre question, mais si vous demandez pourquoi ne pas appeler la super método:

Il y a une raison d'appeler le super s'il n'y a pas de constructeur sans argument dans la classe parent, il n'est pas possible de créer une classe enfant pour cela, donc soit vous devez garder un constructeur sans argument dans la classe parent, soit vous devez définir la méthode super() déclaration d'appel avec argument(how much argument constructor you have used in super class) en haut du constructeur de la classe enfant.

J'espère que cela vous aidera. Si ce n'est pas le cas, faites-le moi savoir.

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