Bir TypeScript sınıfı başka bir sınıftan extends ile kalıtım alır. Alt sınıf ebeveynin her alanını ve metodunu alır, ebeveyn constructor'ını super(...) ile çağırır ve metotları override edebilir; TypeScript de her override'ın ebeveynin tipleriyle uyumlu kaldığını kontrol eder.
Bu, JavaScript sınıf kalıtımıdır (arkasındaki prototip zinciri için JavaScript'te kalıtım sayfasına bakın). TypeScript tip kontrollerini ekler: bir Dog, bir Animal beklenen her yere atanabilir ve derleyici override'ı ve super çağrısını doğrular.
Metotları Override Etmek
Aynı ada sahip bir alt sınıf metodu ebeveyninkinin yerini alır. Tipi ebeveyninkine atanabilir olmalıdır: aynı ya da uyumlu parametreler, aynı ya da daha dar bir dönüş tipi. Aksi halde bir Animal tutan herhangi bir kod, metodu alt sınıfın işleyemeyeceği argümanlarla çağırabilirdi.
Parametreyi value: string yapmak TS2416 hatası olurdu: Property 'format' in type 'CurrencyFormatter' is not assignable to the same property in base type 'Formatter'. Döngü nedenini gösteriyor: hangi alt sınıfa sahip olduğunu bilmeden her elemanda format metodunu bir sayıyla çağırıyor.
Bir açık var. Metot parametreleri bivariant olarak karşılaştırılır, bu yüzden format(value: 1 | 2) gibi daha dar bir tip kabul eden bir override, döngü ona hâlâ 1234567 geçirebilecek olsa da derlenir. Dönüş tipleri ise sıkı biçimde kontrol edilir: string yerine number döndürmek TS2416 hatasıdır.
override Anahtar Kelimesi ve noImplicitOverride
override "bu üye temel sınıftaki bir üyenin yerini alıyor" der ve derleyici sizi bu söze bağlı tutar. Temel sınıfta böyle bir üye yoksa (bir yazım hatası ya da birinin ebeveynde adını değiştirdiği bir metot) bu bir hatadır:
index.ts(9,14): error TS4117: This member cannot have an 'override' modifier because it is not declared in the base class 'Animal'. Did you mean 'speak'?
override olmadan bu yazım hatası derlenir ve speak() sessizce "..." döndürür. Anahtar kelime yalnızca yazıldığı yerde işe yarar, bu yüzden tsconfig.json içinde noImplicitOverride seçeneğini açın. O zaman bir temel sınıf üyesini override eden her metot bunu belirtmek zorundadır ve bir alt sınıftaki düz bir speak(), TS4114 hatası olur (This member must have an 'override' modifier because it overrides a member in the base class 'Animal').
{
"compilerOptions": {
"strict": true,
"noImplicitOverride": true
}
}
noImplicitOverride, strict kapsamında değildir; onu kendiniz eklemeniz gerekir. override derlenmiş JavaScript'ten silinir.
Alt Sınıflarda protected Üyeler
Ebeveynin private üyeleri alt sınıfta görünmez. protected üyeler ise görünür ve protected belirleyicisinin var olma nedeni de budur: bir ebeveyn sınıfın çocuklarına sunduğu API'dir.
Ne private ne de protected belirleyicisinin çalışma zamanında neden korunmadığı dahil tüm kurallar için erişim belirleyiciler sayfasına bakın.
Bir Alanı Daha Dar Bir Tiple Yeniden Bildirmek
Bir alt sınıf çoğu zaman bir alanın ebeveynin söylediğinden daha belirli bir şey tuttuğunu bilir. Onu pet: Dog olarak yeniden bildirmenin modern sınıf alanlarında çalışma zamanı etkisi vardır: alt sınıf alanı super() döndükten sonra undefined ile başlatılır ve ebeveyn constructor'ının kaydettiği değeri siler. Alt sınıf constructor'ı onu yeniden atamadıkça TypeScript bunu TS2612 olarak bildirir (Property 'pet' will overwrite the base property in 'Home'). Yalnızca tipi değiştirmek için declare kullanın:
declare hiçbir şey üretmez, bu yüzden Home constructor'ının ayarladığı değer korunur. Daha dar tipi doğru kılan şey, yalnızca bir Dog kabul eden constructor'dır.
implements ve extends
İki anahtar kelime farklı sorulara cevap verir ve bir sınıf ikisini birden kullanabilir.
extends | implements | |
|---|---|---|
| Neyle çalışır | tek bir sınıf | istenen sayıda interface (ya da nesne tiplerinin type alias'ları) |
| Kod getirir mi | evet: alanlar, metotlar, constructor | hayır, yalnızca biçimi kontrol eder |
| Çalışma zamanında var mı | evet, prototip zinciri | hayır, silinir |
instanceof çalışır mı | evet | hayır |
| Tipik kullanım | gerçek davranışı paylaşmak | kodun geri kalanına bir biçim sözü vermek |
Bir sınıf yalnızca bir sınıfı genişletebilir (TS1174: Classes can only extend a single class). Birkaç yerden gelen davranışı birleştirmek için birkaç interface implement edin ve kodu kompozisyonla (bir yardımcı nesne tutan bir alan) ya da mixin'lerle paylaşın.
Mixin'ler
Mixin, bir sınıf alıp onun bir alt sınıfını döndüren bir fonksiyondur. Tip kontrolünden geçen bir tür çoklu kalıtım sağlar:
Constructor içindeki any[] zorunludur: TypeScript yalnızca constructor'ı any[] tipinde tek bir rest parametre alan bir mixin tabanını kabul eder. Mixin'ler çalışır ama tipleri ve stack trace'leri okumayı zorlaştırır, bu yüzden önce kompozisyonu deneyin.
Sık Yapılan Hatalar
- Temel constructor'dan override edilebilir bir metot çağırmak. Temel constructor, alt sınıfın alanları başlatılmadan önce çalışır; bu yüzden
this.itemsokuyan bir overrideundefinedgörür vethis.items.push(x)gibi bir çağrı çalışma zamanında birTypeErrorfırlatır. TypeScript bunu yakalamaz. super(...)çağrısını unutmak ya da geç yapmak.TS2377veTS17009hataları; alt sınıfthis'e dokunmadan önce nesneyi ebeveyn oluşturmalıdır.- Bir ebeveyn alanını
declareolmadan yeniden bildirmek. Alt sınıf alanı onuundefinedolarak sıfırlar. - Derin hiyerarşiler. Her seviye çocuğu ebeveynin iç yapısına bağlar. Genellikle iki seviye yeterlidir; ötesinde kompozisyonu ya da interface'leri tercih edin.
Sıkça Sorulan Sorular
TypeScript'te kalıtım nasıl çalışır?
Bir sınıf başka bir sınıftan extends ile kalıtım alır: class Dog extends Animal. Alt sınıf ebeveynin alanlarını ve metotlarını alır, ebeveyn constructor'ını super(...) ile çağırır ve metotları override edebilir. TypeScript, override'ların ebeveynle tip uyumlu kaldığını kontrol eder.
TypeScript'te override anahtar kelimesi ne işe yarar?
override, temel sınıftaki bir metodu veya özelliği değiştiren üyeyi işaretler. Temel sınıfta o ada sahip bir üye yoksa derleyici TS4117 bildirir; bu da yazım hatalarını ve ebeveynde adı değiştirilen üyeleri yakalar. noImplicitOverride açıkken her override bu anahtar kelimeyi taşımak zorundadır (aksi halde TS4114).
TypeScript'te ebeveyn sınıfın bir metodunu nasıl çağırırım?
Alt sınıf metodunun içinde super.methodName(...) kullanın. Constructor içinde super(...) ebeveyn constructor'ını çağırır ve this kullanılmadan önce çalışmalıdır.
TypeScript çoklu kalıtımı destekler mi?
Hayır. Bir sınıf yalnızca bir sınıfı genişletebilir (TS1174: Classes can only extend a single class). İstediği kadar interface implement edebilir; mixin'ler (bir sınıf alıp bir alt sınıf döndüren fonksiyonlar) ise birkaç kaynaktan gelen davranışı birleştirir.
extends ile implements arasındaki fark nedir?
extends bir ebeveyn sınıftan gerçek kod miras alır. implements yalnızca bir sınıfın bir interface'in biçimine uyduğunu kontrol eder ve çalışma zamanında hiçbir şey eklemez. Bir sınıf ikisini birlikte yapabilir: class Dog extends Animal implements Pet.