9
votes

Appeler une méthode remplacée à partir d'un constructeur

Dans l'exemple suivant:

Child Show 0  Child Show 20
  • Pourquoi la sortie est-elle indiquée ci-dessous li> ul>
    class Base {    
        int  x=10;  
    
        Base() {    
          show();
        }  
    
        void show() {   
            System.out.print ("Base Show " +x + "  ");
        }  
    }  
    
    class Child extends Base {   
        int x=20;  
    
        Child() {
            show();
        }  
    
        void show() {    
            System.out.print("Child Show " + x +"  ") ; 
        }  
    
        public static void main( String s[ ] ) {   
            Base obj = new Child();   
        }  
    } 
    
    • Je pensais que les constructeurs ne peuvent accéder que des membres de l'instance une fois que ses super constructeurs sont terminés. li> ul>

      Je pense que ce qui se passe ici est que le Super Constructeur appelle la méthode du spectacle de l'enfant () car cette méthode a été remplacée dans l'enfant. Comme il a été remplacé mais pourquoi la valeur de x 0 et pourquoi est-il capable d'accéder à cette méthode avant que le Super Constructor ait terminé? P> P>


3 commentaires

Le mécanisme de traitement virtuel est-il activé lors de la construction d'un objet? Je doute que ce ne soit pas.


En C ++, cela peut causer un crash.


Efficace Java est une excellente ressource Java et elle passe dans ce genre de détails. À partir de l'article 17: " constructeurs ne doit pas appeler des méthodes excessives , directement ou indirectement (...) Si la méthode de dépassement dépend de toute initialisation effectuée par le constructeur de sous-classe, la méthode ne se comportera pas comme attendu. ... "Si vous avez le livre sur place, je recommande vivement de lire cet article.


4 Réponses :


12
votes

Je pense que ce qui se passe ici est que le Super Constructeur appelle la méthode de la série de l'enfant () car cette méthode était remplacée dans l'enfant.

c'est correct

Mais pourquoi la valeur de x 0

Parce que ce n'est pas encore initialisé (x d'enfant)

Et pourquoi est-il capable d'accéder à cette méthode avant que le Super Constructor ait terminé?

C'est exactement pourquoi dans un constructeur, vous ne devez jamais appeler une méthode, qui peut être remplacée (public non finale et protégée).

EDIT:

La chose étrange ici est que tout a une visibilité par défaut / package-privée. Cela peut avoir des effets étranges. Voir: http: // www.cooljeff.co.uk/2009/05/03/Le-subtleties-of-overriding-package-private-methods/

Je recommande d'éviter les méthodes de remplacement de la visibilité par défaut si possible (vous pouvez l'empêcher de les déclarer finale).


4 commentaires

+1 La séquence est principale -> enfant () -> base () -> enfant.show () [x non encore initialisé] -> base.show () [précédé par base.x = 20]


Non, la séquence est principale -> base () -> enfant.show () [x non encore initialisée] -> enfant () [enfant.x = 20] -> enfant.show ()


La variable X sur la classe enfant a-t-elle reçu une valeur par défaut de 0 lorsque la classe d'objet est terminée? Parce que je me souviendrai ici, c'est la séquence: nouvel enfant () -> base () -> Objet -> Implémentation de l'enfant du spectacle () ...


@Anathema La classe d'objets ne définit aucun champ. Mais Afaik, la valeur par défaut est définie lors de la répartition de la mémoire, alors quelque chose comme: principale -> Allocation de mémoire enfant sur le tas avec des valeurs par défaut -> Objet () -> Base () -> Enfant.show () [x Pas encore initialisé] -> Enfant () [enfant.x = 20] -> Enfant.show ()



6
votes

Vous pouvez appeler des méthodes de remplacement des constructeurs, mais c'est mauvais et vous ne devrait pas . Vous avez illustré la raison pour laquelle ceci est mauvais: la classe dérivée n'a aucune chance d'obtenir initialement, des champs non inijialisés seront utilisés - dans votre exemple, la valeur par défaut pour int x est 0 , c'est pourquoi il est d'impression 0 .


0 commentaires

1
votes

Child S de la méthode montre est invoqué car c'est ce que la spécification Java appelle. Voici un Une grande discussion sur la raison pour laquelle vous ne devriez pas le faire . La valeur de x est zéro car enfant n'a pas encore fini d'initialisation.


0 commentaires

2
votes

Constructeur enchaînant qu'il est logique d'expliquer exactement ce que c'est. La première tâche de la méthode du constructeur de sous-classe consiste à appeler la méthode du constructeur de sa superclasse. Cela garantit que la création de l'objet de sous-classe commence par l'initialisation des classes au-dessus de celle-ci dans la chaîne d'héritage.

http: //java.about.com/b/2009/02/07/java-term-of-the-week-constructor-chaining.htm

http://javahours.blogspot.com/2008/12/constructeur- Chain.html


0 commentaires