Arayüzler ve temel sınıfların bir kombinasyonunu kullanmanın sizin için yararlı olabileceğine inanıyorum. Bu, derleme zamanında davranışsal gereksinimleri zorunlu kılar (rq_ post "below" yukarıdaki bir gönderiyi belirtir, bu değil).
Arabirim, temel sınıf tarafından karşılanmayan davranışsal API'yi ayarlar. Arayüzde tanımlanan yöntemleri çağırmak için temel sınıf yöntemlerini ayarlayamazsınız (çünkü bu davranışları tanımlamak zorunda kalmadan bu arabirimi temel sınıfta uygulayamazsınız). Belki birisi ebeveynte arayüz yöntemlerinin çağrılmasına izin vermek için güvenli bir numara yapabilir .
Anlatacağınız sınıfı genişletmeyi ve uygulamayı hatırlamalısınız. Çalışma zamanı hatası kodunu tanımlama endişelerini giderir. Ayrıca, arabirimi uygulamadıysanız (örneğin Animal sınıfını başlatmaya çalıştığınızda) kusacak yöntemleri bile çağıramazsınız. Arayüzü aşağıdaki BaseAnimal genişletmek zorunda çalıştı, ancak yapıcı ve BaseAnimal 'isim' alanı Snake sakladı. Bunu yapabilseydim, bir modülün ve ihracatın kullanılması BaseAnimal sınıfının kazara doğrudan örneklenmesini engelleyebilirdi.
İşinize yarayıp yaramadığını görmek için buraya yapıştırın: 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);
Aşağıda bağlantılı olarak FristvanCampen'in cevabına rastladım. Soyut sınıfların bir anti-desen olduğunu söylüyor ve bir uygulayıcı sınıfın enjekte edilmiş bir örneğini kullanarak bir anlık temel 'soyut' sınıfların olduğunu öne sürüyor. Bu adil, ama karşı argümanlar yapıldı. Kendiniz okuyun:
https://typescript.codeplex.com/discussions/449920
Bölüm 2: Soyut bir sınıf istediğim başka bir durumum vardı, ancak yukarıdaki çözümü kullanmam engellendi, çünkü "soyut sınıf" daki tanımlı yöntemlerin eşleşen arayüzde tanımlanan yöntemlere başvurması gerekiyordu. Ben de FristvanCampen'in tavsiyesini kullanıyorum. Metot uygulamaları ile eksik "soyut" sınıfım var. Uygulanmayan yöntemlerle ara yüzüm var; bu arabirim "soyut" sınıfı genişletir. Sonra ilk genişleten ve ikinci uygular bir sınıf var (süper yapıcı aksi takdirde erişilemez çünkü her ikisini de uzatmak gerekir). Aşağıdaki (çalıştırılamaz) örneğe bakı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;
}
}
ve
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;
}