我认为使用接口和基类的组合可能对您有用。它将在编译时强制执行行为要求(rq_post "below"是指上面的帖子,而不是本帖)。
接口设置未被基类满足的行为API。您将无法设置基类方法以调用在接口中定义的方法(因为您将无法在基类中实现该接口而不必定义这些行为)。也许有人可以想出一个安全的技巧来允许在父级中调用接口方法。
您必须记住在您将要实例化的类中扩展和实现。它满足了定义运行时失败代码的关注点。如果您尝试实例化动物类,则甚至无法调用会引起错误的方法(例如,如果您尝试实例化Animal类)。我尝试让接口扩展下面的BaseAnimal,但它隐藏了构造函数和BaseAnimal的“name”字段,使Snake的情况更加复杂。如果我能够做到这一点,使用模块和导出可能会防止意外直接实例化BaseAnimal类。
将此粘贴到这里以查看是否适用于您:
http://www.typescriptlang.org/Playground/
interface AbstractAnimal extends BaseAnimal {
makeSound(input : string): string;
}
class BaseAnimal {
constructor(public name) { }
move(meters) {
alert(this.name + " moved " + meters + "m.");
}
}
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");
fulture.move(1);
我看到了FristvanCampen的回答,如下链接。他认为抽象类是一种反模式,并建议使用实现类的注入实例来实例化基类'abstract'类。这是公平的,但也有相反的观点。请自行阅读:
https://typescript.codeplex.com/discussions/449920
第二部分:
我遇到了另一个案例,我想要一个抽象类,但我不能使用上述的解决方案,因为“抽象类”中定义的方法需要引用匹配接口中定义的方法。所以,我采用了FristvanCampen的建议。我有未完成的“抽象”类,其中包含方法实现。我有未实现方法的接口;这个接口扩展了“抽象”类。然后我有一个类,它继承了第一个类并实现了第二个类(必须继承两个类,否则超级构造函数将不可访问)。以下是样例(不可运行):
export class OntologyConceptFilter extends FilterWidget.FilterWidget<ConceptGraph.Node, ConceptGraph.Link> implements FilterWidget.IFilterWidget<ConceptGraph.Node, ConceptGraph.Link> {
subMenuTitle = "Ontologies Rendered";
constructor(
public conceptGraph: ConceptGraph.ConceptGraph,
graphView: PathToRoot.ConceptPathsToRoot,
implementation: FilterWidget.IFilterWidget<ConceptGraph.Node, ConceptGraph.Link>
){
super(graphView);
this.implementation = this;
}
}
并且
export class FilterWidget<N extends GraphView.BaseNode, L extends GraphView.BaseLink<GraphView.BaseNode>> {
public implementation: IFilterWidget<N, L>
filterContainer: JQuery;
public subMenuTitle : string;
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;
}