2
votes

Accéder à la propriété de classe JavaScript dans la classe parent

Y a-t-il un moyen que cela soit possible dans ES6 - ou y a-t-il une bonne solution si ce n'est pas (comme cela semble fonctionne!)


2 commentaires

developer.mozilla.org/en-US/docs/ Web / JavaScript / Référence /…


Je comprends cet exemple d'appel de la méthode d'un parent avec super (). Il s'agit de savoir si la référence du constructeur Parent à this.name pointe vers le nom défini dans Child - au point où Parent.constructor est appelé. (Cela ne semble pas fonctionner)


4 Réponses :


1
votes

Le constructeur d'un parent est appelé avant que l'enfant puisse initialiser ses données d'instance afin que vous ne puissiez pas faire référence à l'instance d'un enfant dans le constructeur du parent. C'est tout simplement une mauvaise conception de la POO (au moins en Javascript). Si le parent veut accéder à une propriété dans le constructeur, définissez et initialisez la propriété dans le constructeur du parent (l'enfant peut toujours l'utiliser).

Les parents ne devraient pas dépendre des enfants - les enfants dépendent du parent.

Donc, cette conception de la POO est défectueuse. Vous ne montrez pas le problème réel que vous essayez de résoudre, nous ne pouvons donc pas vraiment suggérer quelle serait la bonne conception pour le problème réel.


Pour vérifier, l'ordre des choses est :

  1. Le constructeur enfant est appelé
  2. Le constructeur enfant appelle super (...) pour exécuter le constructeur parent
  3. Le constructeur parent initialise ses données d'instance
  4. Après le retour du constructeur parent, le constructeur enfant a la possibilité d'initialiser ses données d'instance

Si vous utilisez des définitions de classe ES6, vous ne pouvez pas changer ce séquencement en quelque chose de différent.


D'après votre dernier commentaire sur cette réponse, je ne pense pas il y a vraiment un meilleur moyen, que d'ajouter simplement les lignes de code supplémentaires à chaque enfant:

class Parent {
    constructor(name) {
        if (!name) {
            // could also throw an exception here if not
            // providing a name is a programming error and is not allowed
            this.name = "Default Name";
        } else {
            this.name = name;
        }
        console.log(this.name);
    }
}

class ChildA extends Parent {
     constructor() {
         super("ChildA Name");
     }
}

class ChildB extends Parent {
     constructor() {
         super("ChildB Name");
     }
}

const c = new ChildA();
// Should console.log "ChildA Name";


5 commentaires

Quelques idées fausses ici. 1. "First, name =" Child Name "; ne fait pas référence à une propriété de l'objet." OP utilise la syntaxe de champ de classe, actuellement un proposition étape 2 . 2. "Deuxièmement, votre enfant doit appeler le constructeur du parent avec super () . Troisièmement, votre définition enfant n'est pas la syntaxe ES6 correcte. Vous devrez définir un constructeur enfant." Une classe dérivée n'est pas nécessaire pour définir un constructeur . S'il n'est pas défini, le constructeur de la superclasse est appelé implicitement.


"Quatrièmement, le constructeur d'un parent est appelé avant que l'enfant ne puisse initialiser ses données d'instance afin que vous ne puissiez pas faire référence à l'instance d'un enfant dans le constructeur du parent." Cette partie est correcte, au moins.


Cela semble être la réponse que je recherchais. Bref, non, pas possible. J'essayais de créer un objet de données dans Parent qui (entre autres) contient le champ name de l'enfant qui l'a inséré. Je me demandais s'il y avait un moyen de le faire sans avoir à définir un constructeur sur chaque classe enfant (il y en a beaucoup) et à récupérer simplement la propriété de classe de la classe enfant. (Pour que le bit qui change pour chaque classe enfant soit juste une ligne, pas quatre lignes de constructeur dont je n'ai pas besoin sauf pour définir une seule variable.) Mais oui, impossible car le Parent est initialisé en premier.


@ user2672537 - J'ai ajouté un exemple de code. IMO, le moyen le plus propre d'implémenter cela à l'aide de classes ES6 consiste simplement à ajouter les lignes de code supplémentaires pour définir le constructeur enfant.


@JordanRunning - Pour info, j'ai nettoyé ma réponse en fonction de vos commentaires et ajouté des informations supplémentaires basées sur les commentaires du PO.



2
votes

Pour conserver la valeur de la propriété name du parent, vous pouvez simplement laisser le constructeur hors de votre classe enfant. Sinon, si vous souhaitez mettre à jour une propriété spécifique ( name dans ce cas), vous devez définir this.name dans le constructeur APRÈS a appel à super () - un appel explicite à super () est nécessaire avant de pouvoir définir les propriétés de this , sinon JavaScript générera une erreur.

Voici un exemple de ce que j'essaie d'expliquer ci-dessus:

class Parent {
  constructor() {
    this.name = "Parent Name";
  }
}

class ChildWithConstructor extends Parent {
  constructor() {
    super();
    this.name = "Child Name";
  }

  sayName() {
    console.log(`The constructor call updated the property value set in the parent contructor: ${this.name}`)
  }
}

class ChildWithoutConstructor extends Parent {
  sayName() {
    console.log(`No constructor call retains the property values set in the parent contructor: ${this.name}`)
  }
}

const c = new ChildWithConstructor();
const nc = new ChildWithoutConstructor();
c.sayName();
nc.sayName();


1 commentaires

Il semble que ce que je veux faire est en fait impossible. Pour plus de contexte, le constructeur Parent allait commencer à construire une sorte d'objet de données, dont l'une des valeurs était la variable Child.name (de sorte que l'objet de données garde une trace de laquelle des nombreuses les classes enfants ont été réellement instanciées). Mais, comme le dit la réponse de jfriend00, «le constructeur d'un parent est appelé avant que l'enfant ne puisse initialiser ses données d'instance» (ce qui suggérerait que ce que je veux faire est impossible).



0
votes

Depuis la classe parent , l'accès aux champs de la classe enfant ne peut pas être obtenu. De l'enfant au parent - vous pouvez utiliser super

    class Parent {    
        constructor() {
          this.name="Parent Name";      
        };
    }

    class Child extends Parent {
      constructor(){
        super(name);
        console.log(this.name);
        this.name = "Child Name";
        console.log(this.name);    
      }
    }

    const c = new Child();


0 commentaires

1
votes

le seul moyen est d'appeler une méthode nommée init sur le constructeur enfant et de la définir sur la classe parent et d'utiliser la méthode init comme constructeur parent.

de cette manière, init sera appelé lorsque les propriétés enfants seront prêtes p >

class Parent {
    constructor() {
      
    }
    
    init() {
      console.log(this.name);
    }
}

class Child extends Parent {
     name = "Child Name";
     
     constructor() {
      super();

      // call parent init
      this.init();
    }
}

const c = new Child();


0 commentaires