Menu
Playground'da Dene

JavaScript Kalıtım: extends, super ve Metot Geçersiz Kılma

JavaScript sınıflarında kalıtımın nasıl çalıştığı: extends, super, metot override etme ve kalıtımın yanlış tercih olduğu durumlar.

Bir Sınıfın Başka Bir Sınıftan Türemesi

JavaScript'te kalıtım sayesinde bir sınıfı sıfırdan yazmak yerine var olan bir sınıfın üzerine inşa edebilirsiniz. Üst sınıftaki tüm alanlar ve metotlar hazır şekilde size gelir; siz de istediğinizi ekler, istediğinizi değiştirirsiniz:

index.js
Output
Click Run to see the output here.

Dog extends Animal şu anlama gelir: "bir Dog aslında bir Animal'dır, üstüne biraz daha fazlası." rex nesnesinin kendine ait bir speak metodu yok ama arama zinciri Animal'a kadar düşüyor ve orada buluyor. İşte tüm olay bu düşme mekanizması — aslında prototip tabanlı kalıtımın biraz daha şık bir sözdizimiyle sunulmuş hali.

Constructor içinde super kullanımı

Kendi constructor'ına sahip bir alt sınıfın uyması gereken katı bir kural var: this'e dokunmadan önce mutlaka super(...) çağrılmalı. super, üst sınıfın constructor'ını çalıştırır; nesneyi asıl oluşturan ve ilk değerlerini atayan da odur:

index.js
Output
Click Run to see the output here.

super(name) satırını atlarsan, this'e dokunmaya çalıştığın anda ReferenceError yersin. Motor, ebeveyn sınıf üstüne düşeni yapmadan sana this'i vermeyi resmen reddediyor.

Alt sınıf kendi constructor'ını tanımlamazsa, JavaScript senin için otomatik olarak bir tane üretir ve tüm argümanları super'e iletir. Yani constructor yazmana ancak yeni alanlar eklemek ya da ekstra bir kurulum yapmak istediğinde gerek var.

Metotları Override Etmek

Alt sınıf, miras aldığı herhangi bir metodu yeniden tanımlayabilir. Prototip zincirinde en yakındaki metot kazanır:

index.js
Output
Click Run to see the output here.

Burada sihir yok — bir Dog üzerinde speak() çağırdığında motor önce örneğe, sonra Dog.prototype'a bakar, speak'i orada bulur ve durur. Animal.prototype'a hiç ulaşmaz.

Ezmek Değil, Genişletmek: super.method()

Bazen üst sınıfın metodunu tamamen değiştirmek istemezsin — üstüne bir şeyler eklemek istersin. İşte tam bu noktada super.method(...) devreye giriyor; override ettiğin metodun içinden üst sınıfın orijinal versiyonunu çağırmanı sağlıyor:

index.js
Output
Click Run to see the output here.

İşte kalıtımın asıl işe yaradığı nokta: alt sınıf, üst sınıfın mantığını kopyalamak yerine doğrudan yeniden kullanır. İleride Animal.describe değişirse, Dog.describe bu değişikliği hiçbir ek iş yapmadan otomatik olarak devralır.

super anahtar kelimesi yalnızca constructor içinde değil, her metotta çalışır. Her zaman, o an çağırdığınız şeyin üst sınıftaki versiyonunu ifade eder.

instanceof ve Prototip Zinciri

instanceof, bir nesnenin prototip zincirinde belirli bir sınıfın bulunup bulunmadığını kontrol eder. Her alt sınıf örneği, aynı zamanda üst sınıflarının da bir örneğidir:

index.js
Output
Click Run to see the output here.

Dördü de true döner. Zincir şu şekilde ilerliyor: Puppy -> Dog -> Animal -> Object, ve instanceof bu zinciri baştan sona takip ediyor. Tip kontrolü için kullanışlı bir araç; ama pratikte düşündüğünüzden çok daha az ihtiyaç duyarsınız — genelde metotları çağırmanız yeterli olur, gerisini polimorfizm halleder.

Biraz Daha Kapsamlı Bir Örnek

Sıkça karşılaşılan bir kalıp: ortak mantığı barındıran bir temel sınıf ve onu özelleştiren birkaç alt sınıf.

index.js
Output
Click Run to see the output here.

describe metodunun Shape içinde yaşadığına ve bir daha yazılmasına gerek olmadığına dikkat edin — sadece this.area() çağırıyor ve bu da çalışma zamanında doğru alt sınıfa çözümleniyor. İşte polimorfizm tam da bu: aynı çağrı noktası, gerçek nesneye göre farklı davranış.

JavaScript inheritance vs composition

Kalıtım ilk bakışta cazip gelir, çünkü verimli hissettirir — tek satırla bir sürü metoda kavuşuyorsunuz. Ama hiyerarşiler büyüdükçe işler sarpa sarar.

Pratik bir kural: extends kullanımını, ilişki net biçimde "X bir Y'dir" şeklinde olduğunda ve alt sınıf gerçekten üst sınıfın davranışının büyük kısmını paylaştığında tercih edin. Sırf bir iki yardımcı metodu paylaşmak için kalıtıma sarılıyorsanız, onun yerine kompozisyonu seçin — sınıfa, yardımcı nesneyi tutan bir alan verin:

index.js
Output
Click Run to see the output here.

Derin kalıtım ağaçları (Animal -> Mammal -> Dog -> WorkingDog -> PoliceDog) diyagramlarda şık görünür ama kodda başınızı ağrıtır — kökte yapılan küçük bir değişiklik, tüm alt sınıflara öngörülemez biçimde yayılır. Sağlıklı kod tabanlarının çoğu bir ya da iki seviyede kalır, gerisini kompozisyonla halleder.

Sırada: Static Üyeler

Bu dokümandaki her şey örnekler (instance) üzerinde çalışıyor — yani new Thing().something() şeklinde çağırdığınız metotlar. Ama bazen sınıfın kendisine ait, herhangi bir örneğe bağlı olmayan metot veya veriler istersiniz. İşte static tam da bunun için var; bir sonraki konumuz bu.

Sıkça Sorulan Sorular

JavaScript'te kalıtım (inheritance) nasıl çalışır?

Bir sınıf, extends ile başka bir sınıftan türetilebilir. Alt sınıf, üst sınıfın tüm metotlarını ve alanlarını devralır; üstüne kendi metotlarını ekleyebilir ya da mevcut olanları override edebilir. Arka planda JavaScript, alt sınıfın prototype'ını üst sınıfın prototype'ına bağlar; bu sayede metot araması prototip zincirinde otomatik olarak yukarı doğru ilerler.

JavaScript'te super ne işe yarar?

super(...) üst sınıfın constructor'ını çağırır — alt sınıfın constructor'ında this'i kullanmadan önce mutlaka super(...) çağrısı yapılmalıdır. super.method(...) ise üst sınıftaki metodun orijinal halini çağırır; yani metodu tamamen ezmek yerine üzerine davranış eklemek istediğinde işine yarar.

JavaScript'te kalıtım mı yoksa composition mı kullanmalıyım?

Ortada gerçek bir 'is-a' ilişkisi varsa ve alt sınıf, üst sınıfın davranışının büyük kısmını paylaşıyorsa kalıtım mantıklıdır. Ama sadece ortak işlevsellik paylaşmak istiyorsan composition'a yönel — yani bir nesnenin içinde başka nesneler tut. Derin sınıf hiyerarşileri zamanla başa bela olmaya eğilimlidir; gerçek projelerin çoğu bir ya da iki seviyeden öteye gitmez.

Coddy ile kodlamayı öğren

BAŞLA