インターフェイスと基本クラスを組み合わせて使用すると、うまくいくと思います。コンパイル時に動作要件を適用します(rq_ post "below"は上記の投稿を指しますが、これはこれではありません)。
インターフェイスは、基本クラスが満たさない動作APIを設定します。インターフェイスで定義されたメソッドを呼び出すように基本クラスのメソッドを設定することはできません(これらの動作を定義せずに基本クラスにそのインターフェイスを実装することはできないため)。たぶん誰かが親のインターフェースメソッドの呼び出しを可能にする安全なトリックを思い付くことができます。
インスタンス化するクラスを拡張して実装することを忘れないでください。これは、ランタイム失敗コードの定義に関する懸念を満たします。また、インターフェイスを実装していない場合(Animalクラスをインスタンス化しようとした場合など)、pukeするメソッドを呼び出すこともできません。以下のBaseAnimalをインターフェイスに拡張させてみましたが、コンストラクターとBaseAnimalの「name」フィールドがSnakeから隠されていました。それができれば、モジュールとエクスポートを使用することで、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の答えに出くわしました。彼は、抽象クラスはアンチパターンであり、実装クラスの注入されたインスタンスを使用して、1つのインスタンス化されたベース「抽象」クラスを提案します。これは公正ですが、反論があります。自分で読んでください:
https ://typescript.codeplex.com/discussions/449920
パート2:抽象クラスが必要な別のケースがありましたが、「抽象クラス」で定義されたメソッドが一致するインターフェイスで定義されたメソッドを参照する必要があるため、上記のソリューションを使用できませんでした。だから、私はFristvanCampenのアドバイスを使っています。メソッドの実装を含む、不完全な「abstract」クラスがあります。実装されていないメソッドとのインターフェースがあります。このインターフェースは「abstract」クラスを拡張します。次に、最初のクラスを拡張し、2番目のクラスを実装するクラスがあります(スーパーコンストラクターにはアクセスできないため、両方を拡張する必要があります)。以下の(実行不可能な)サンプルを参照してください。
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;
}