Creo que usar una combinación de interfaces y clases base podría funcionar para usted. Hará cumplir los requisitos de comportamiento en tiempo de compilación (rq_ post "a continuación" se refiere a un post anterior, que no es este).
La interfaz establece la API de comportamiento que no cumple la clase base. No podrá establecer métodos de clase base para invocar métodos definidos en la interfaz (porque no podrá implementar esa interfaz en la clase base sin tener que definir esos comportamientos). Tal vez alguien pueda idear un truco seguro para permitir la llamada de los métodos de interfaz en el padre.
Debe recordar extender e implementar en la clase que va a instanciar. Satisface las preocupaciones sobre la definición del código de tiempo de ejecución de falla. Tampoco podrá llamar a los métodos que vomitarían si no ha implementado la interfaz (por ejemplo, si intenta crear una instancia de la clase Animal). Intenté que la interfaz extendiera BaseAnimal a continuación, pero ocultó el constructor y el campo 'nombre' de BaseAnimal de Snake. Si hubiera podido hacer eso, el uso de un módulo y las exportaciones podrían haber evitado la creación de instancias directas accidentales de la clase BaseAnimal.
Pegue esto aquí para ver si funciona para usted: 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);
Encontré la respuesta de FristvanCampen como se vincula a continuación. Él dice que las clases abstractas son un antipatrón, y sugiere que se instancian las clases 'abstractas' base utilizando una instancia inyectada de una clase implementadora. Esto es justo, pero hay argumentos en contra. Léalo usted mismo:
https://typescript.codeplex.com/discussions/449920
Parte 2: tuve otro caso en el que quería una clase abstracta, pero se me impidió usar mi solución anterior, porque los métodos definidos en la "clase abstracta" debían referirse a los métodos definidos en la interfaz correspondiente. Por lo tanto, utilizo el consejo de FristvanCampen, más o menos. Tengo la clase "abstracta" incompleta, con implementaciones de métodos. Tengo la interfaz con los métodos no implementados; esta interfaz extiende la clase "abstracta". Luego tengo una clase que extiende el primero e implementa el segundo (debe extender ambos porque el súper constructor es inaccesible de lo contrario). Vea la muestra (no ejecutable) a continuación:
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;
}
}
y
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;
}