我相信结合使用接口和基类可以为您工作。它将在编译时强制执行行为要求(rq_帖子“以下”是指上面的帖子,而不是此帖子)。
该接口设置了基类无法满足的行为API。您将无法设置基类方法来调用接口中定义的方法(因为如果不定义这些行为,就无法在基类中实现该接口)。也许有人可以提出一个安全的技巧,以允许在父级中调用接口方法。
您必须记住要在要实例化的类中进行扩展和实现。它满足了有关定义运行时失败代码的担忧。如果您尚未实现接口(例如,如果您尝试实例化Animal类),您甚至将无法调用会呕吐的方法。我试图让接口扩展下面的BaseAnimal,但是它从Snake隐藏了构造函数和BaseAnimal的“名称”字段。如果我能够做到这一点,则使用模块和导出可以避免意外地直接实例化BaseAnimal类。
将此粘贴在这里,看看是否适合您: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);
我遇到了FristvanCampen的回答,如下所示。他说抽象类是一种反模式,并建议使用实例化类的注入实例实例化基础“抽象”类。这是公平的,但有相反的论点。亲自阅读:https:
//typescript.codeplex.com/discussions/449920
第2部分:在另一种情况下,我想要一个抽象类,但是由于“抽象类”中定义的方法需要引用匹配接口中定义的方法,因此无法使用我的解决方案。因此,我采用了FristvanCampen的建议。我有不完整的“抽象”类,带有方法实现。我有未实现方法的接口;此接口扩展了“抽象”类。然后,我有一个扩展第一个类并实现第二个类的类(它必须同时扩展两个类,因为否则无法访问超级构造函数)。请参见下面的(不可运行的)示例:
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;
}
}
和
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;
}