3 votes

Classes javascript : comment accéder aux fonctions de la classe mère dans le code de la classe mère ?

Javascript ES6 ( node 8.4.0 et la dernière version de chrome et de Firefox )

Je m'attendais à

class Parent {
    init(){
        console.log("Parent init") ;
        this._surname = "McClass" ;
    }
    constructor() {
        console.log("Parent constructor") ;
        this.init();
    }

    get surname(){
        return this._surname ;
    }
}

class Child extends Parent {

    init(){
        console.log("Child init") ;
    }
    constructor() {
        super();
        console.log("Child constructor") ;
        this.init();
    }    
}

var child = new Child() ;

console.log(child.surname);

pour obtenir le résultat suivant ;

Parent constructor
Parent init
Child constructor
Child init
McClass

(c'est ce que donne un code C++ comparable)

Hélas, j'ai reçu ceci ;

Parent constructor
Child init
Child constructor
Child init
undefined

Est-ce que je fais quelque chose de mal ou est-ce que c'est le bon comportement à adopter et si oui, comment cela se justifie-t-il ?

EDIT ;

Voir la réponse de MinusFour ci-dessous sur la façon de réaliser ce que j'essayais de faire/attendais.

Quant à savoir pourquoi le résultat observé est le comportement "correct" et justifié ;

Comme Bergi l'a souligné (dans les commentaires), tous les appels à des méthodes d'objets en js sont effectivement "virtuels" (la dernière méthode de ce nom ajoutée à la chaîne d'héritage du prototype de l'objet étant la première trouvée et donc exécutée). Il s'avère que les appels sont toujours virtuels dans un contexte de construction de classe.

Le C++ n'applique pas le comportement des méthodes virtuelles pendant la construction, mais Java le fait et vous obtenez le même résultat (comme ci-dessus) dans un code Java comparable ; il y a donc un précédent pour le comportement observé.

2voto

MinusFour Points 1001

Vous pouvez le faire :

Parent.prototype.init.call(this);

class Parent {
  init() {
    console.log("Parent init");
    this._surname = "McClass";
  }
  constructor() {
    console.log("Parent constructor");
    Parent.prototype.init.call(this);
  }

  get surname() {
    return this._surname;
  }
}

class Child extends Parent {

  init() {
    console.log("Child init");
  }
  constructor() {
    super();
    console.log("Child constructor");
    this.init();
  }
}

var child = new Child();

Pour s'assurer qu'il n'est jamais surchargé, mais je vous suggère de ne pas le surcharger en premier lieu.

0voto

estus Points 5252

Il s'agit d'un comportement attendu, simplement parce qu'il peut être observé dans les implémentations de classes ES6 établies qui suivent les spécifications.

this fait référence à l'instance de classe actuelle, qui est une instance de Child dans le cas où Child est instancié - même dans Parent parce qu'il n'y a qu'une seule instance et qu'elle est instanceof Child .

Si Child surcharge la méthode, il est de sa responsabilité de fournir un mécanisme pour l'appeler. Si l'on considère que la méthode init suit une convention documentée et est l'endroit où l'initialisation de la classe a lieu afin de rendre le constructeur plus léger et plus testable, il l'est :

class Parent {
    init(){...}
    constructor() {
        this.init();
    }
    ...
}

...

class Child extends Parent {
    init(){
        super.init();
        ...
    }
    // optional, as long as `init` contains all init logic
    constructor() {
        super();
    }    
}

Ce qui donne une séquence :

Parent constructor
Parent init
Child init
Child constructor

Si init est censé fonctionner de manière totalement indépendante dans les deux classes, il ne doit pas être surchargé. Les méthodes doivent être nommées différemment, comme initParent y initChild . Ou tout autre moyen d'éviter les collisions de noms peut être utilisé, par exemple :

const init = Symbol('Parent init');
class Parent {
    [init](){...}
    constructor() {
        this[init]();
    }
    ...
}

...

const init = Symbol('Child init');
class Child extends Parent {
    [init](){...}
    constructor() {
        this[init](); // totally independent method
    }
}

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