Je crois que l'utilisation d'une combinaison d'interfaces et de classes de base pourrait travailler pour vous. Il va appliquer comportementale exigences au moment de la compilation (rq_ post "ci-dessous" fait référence à un post ci-dessus, ce qui n'est pas celui-ci).
L'interface définit le comportement de l'API qui n'est pas rencontré par la classe de base. Vous ne serez pas en mesure de définir des méthodes de classe de base pour appeler sur les méthodes définies dans l'interface (parce que vous ne serez pas en mesure de mettre en œuvre cette interface dans la classe de base, sans avoir à définir ces comportements). Peut-être quelqu'un peut venir avec un coffre-fort astuce pour permettre d'appeler des méthodes d'interface dans le parent.
Vous devez vous rappeler de les étendre et de les mettre en œuvre dans la classe que vous instancier. Il répond à des préoccupations au sujet de la définition à l'exécution code de non. En outre, vous ne même pas être en mesure d'appeler les méthodes de vomir si vous n'avez pas mis en œuvre l'interface (comme si vous essayez d'instancier l'Animal de la classe). J'ai essayé d'avoir l'interface de prolonger la BaseAnimal ci-dessous, mais il se cachait, le constructeur et le champ 'nom' de BaseAnimal de Serpent. Si j'avais été capable de le faire, l'utilisation d'un module et les exportations auraient empêché accidentel direct de l'instanciation de la BaseAnimal classe.
Collez ce ici pour voir si cela fonctionne pour vous: http://www.typescriptlang.org/Playground/
// The behavioral interface also needs to extend base for substitutability
interface AbstractAnimal extends BaseAnimal {
// encapsulates animal behaviors that must be implemented
makeSound(input : string): string;
}
class BaseAnimal {
constructor(public name) { }
move(meters) {
alert(this.name + " moved " + meters + "m.");
}
}
// If concrete class doesn't extend both, it cannot use super methods.
class Snake extends BaseAnimal implements AbstractAnimal {
constructor(name) { super(name); }
makeSound(input : string): string {
var utterance = "sssss"+input;
alert(utterance);
return utterance;
}
move() {
alert("Slithering...");
super.move(5);
}
}
var longMover = new Snake("windy man");
longMover.makeSound("...am I nothing?");
longMover.move();
var fulture = new BaseAnimal("bob fossil");
// compile error on makeSound() because it is not defined.
// fulture.makeSound("you know, like a...")
fulture.move(1);
Je suis tombé sur FristvanCampen la réponse de comme lien ci-dessous. Il dit que les classes abstraites sont un anti-modèle, et suggère que l'on instancie la base de "abstrait" classes à l'aide de l'injection d'une instance de mise en œuvre de la classe. C'est juste, mais il existe des contre arguments. Lisez vous-même:
https://typescript.codeplex.com/discussions/449920
Partie 2:
J'ai eu un autre cas où je voulais une classe abstraite, mais j'ai été empêché d'utiliser ma solution ci-dessus, parce que les méthodes définies dans la "classe abstraite" nécessaire de se reporter aux méthodes définies dans l'interface correspondant. Donc, je l'outil FristvanCampen les conseils, en quelque sorte. J'ai le incomplète "abstrait" de la classe, avec la méthode mise en œuvre. J'ai l'interface avec les méthodes non implémentées; cette interface s'étend le "résumé" de la classe. J'ai ensuite une classe qui étend la première et met en œuvre la deuxième (il doit s'étendre à la fois parce que le super constructeur est inaccessible autrement). Voir la (non-exécutables) de l'échantillon ci-dessous:
export class OntologyConceptFilter extends FilterWidget.FilterWidget<ConceptGraph.Node, ConceptGraph.Link> implements FilterWidget.IFilterWidget<ConceptGraph.Node, ConceptGraph.Link> {
subMenuTitle = "Ontologies Rendered"; // overload or overshadow?
constructor(
public conceptGraph: ConceptGraph.ConceptGraph,
graphView: PathToRoot.ConceptPathsToRoot,
implementation: FilterWidget.IFilterWidget<ConceptGraph.Node, ConceptGraph.Link>
){
super(graphView);
this.implementation = this;
}
}
et
export class FilterWidget<N extends GraphView.BaseNode, L extends GraphView.BaseLink<GraphView.BaseNode>> {
public implementation: IFilterWidget<N, L>
filterContainer: JQuery;
public subMenuTitle : string; // Given value in children
constructor(
public graphView: GraphView.GraphView<N, L>
){
}
doStuff(node: N){
this.implementation.generateStuff(thing);
}
}
export interface IFilterWidget<N extends GraphView.BaseNode, L extends GraphView.BaseLink<GraphView.BaseNode>> extends FilterWidget<N, L> {
generateStuff(node: N): string;
}