web-dev-qa-db-fra.com

ECMAScript 6 a-t-il une convention pour les classes abstraites?

J'ai été surpris de ne rien trouver à propos des classes abstraites lors de la lecture sur ES6. (Par "classe abstraite", je parle de la signification Java de celle-ci, dans laquelle une classe abstraite déclare les signatures de méthodes qu'une sous-classe doit implémenter pour être instanciables).

Est-ce que quelqu'un connaît des conventions en place pour implémenter des classes abstraites dans ES6? Ce serait bien de pouvoir attraper une violation de classe abstraite avec une analyse statique.

Si je devais générer une erreur au moment de l'exécution pour signaler une tentative d'instanciation de classe abstraite, quelle serait l'erreur?

142
obelia

ES2015 ne dispose pas de classes de style Java avec des abordages intégrés pour votre modèle de conception souhaité. Cependant, certaines options peuvent être utiles, en fonction de ce que vous essayez d'accomplir.

Si vous souhaitez une classe qui ne peut pas être construite, mais dont les sous-classes peuvent, vous pouvez utiliser _new.target_:

_class Abstract {
  constructor() {
    if (new.target === Abstract) {
      throw new TypeError("Cannot construct Abstract instances directly");
    }
  }
}

class Derived extends Abstract {
  constructor() {
    super();
    // more Derived-specific stuff here, maybe
  }
}

const a = new Abstract(); // new.target is Abstract, so it throws
const b = new Derived(); // new.target is Derived, so no error
_

Pour plus de détails sur new.target , vous pouvez lire cet aperçu général du fonctionnement des classes dans ES2015: http://www.2ality.com/2015/02/) es6-classes-final.html

Si vous souhaitez spécifiquement implémenter certaines méthodes, vous pouvez également vérifier cela dans le constructeur de la super-classe:

_class Abstract {
  constructor() {
    if (this.method === undefined) {
      // or maybe test typeof this.method === "function"
      throw new TypeError("Must override method");
    }
  }
}

class Derived1 extends Abstract {}

class Derived2 extends Abstract {
  method() {}
}

const a = new Abstract(); // this.method is undefined; error
const b = new Derived1(); // this.method is undefined; error
const c = new Derived2(); // this.method is Derived2.prototype.method; no error
_
267
Domenic