Kalıtım ve metot ezme
Kalıtım (inheritance), bir sınıfın başka bir sınıfın davranışlarını ve arayüzünü temel alarak özelleşmesini sağlar. Güçlü bir araçtır; ancak yanlış kullanıldığında sıkı bağımlı ve kırılgan sınıf hiyerarşileri oluşturabilir. Bu hafta kalıtımı is-a ilişkisi üzerinden öğrenecek ve kompozisyon alternatifiyle karşılaştıracağız.
Bu hafta neleri yapabilmelisiniz?
- Üst sınıf ve alt sınıf kavramlarını açıklayabilmeli,
class Child(Parent)sözdizimini kullanabilmeli,- Miras alınan metodu çağırabilmeli,
- Metot ezme (override) yapabilmeli,
super()ile hem__init__hem normal bir üst sınıf davranışını genişletebilmeli,isinstance()ile alt tür ilişkisinin etkisini gözlemleyebilmeli,- Liskov yerine geçme ilkesinin temel sorusunu açıklayabilmeli,
is-ailehas-aayrımını kullanarak kalıtımın uygunluğunu tartışabilmeli,- Çoklu kalıtım ve MRO kavramlarını tanıma düzeyinde açıklayabilmelisiniz.
İlk kalıtım örneği
Developer, Employee sınıfından davranış alır. Bir Developer nesnesi aynı zamanda Employee tür ilişkisinin de içindedir; bu nedenle iki isinstance() çağrısı da True olur.
is-a yeterli mi? Liskov yerine geçme ilkesi
Kalıtım için ilk sezgi:
Bir
Developer, birEmployee’dir.
Ama daha güçlü soru şudur:
Bir
Employeebeklenen yerdeDeveloperkullanıldığında üst sınıfın beklenen sözleşmesi bozulmadan program çalışıyor mu?
Bu düşünce yazılım tasarımında Liskov Substitution Principle (LSP) / Liskov yerine geçme ilkesi ile ilişkilidir. Bu derste ilkenin formal tanımını ezberlemiyoruz; alt türün üst türün beklenen davranışını bozup bozmadığını sorguluyoruz.
Override: davranışı özelleştirmek
Alt sınıftaki send, üst sınıftaki aynı adlı metodu ezer (override). Override ederken çağıranın beklediği davranış sözleşmesini korumaya çalışın.
super() yalnızca __init__ için değildir
Önce kurucuda yeniden kullanım:
super().__init__(name), üst sınıf kurulumunu tekrar yazmamayı sağlar.
Asıl davranışı genişletme örneği normal metotta da görülebilir:
Burada alt sınıf üst davranışı tamamen silip yeniden yazmak yerine çağırır ve sonucu genişletir.
is-a ve has-a
| İlişki | Örnek | Tipik araç |
|---|---|---|
| is-a | Developer bir Employee’dir |
kalıtım |
| has-a | Car bir Engine’e sahiptir |
kompozisyon |
Ortak alan veya metot bulunması tek başına kalıtım gerekçesi değildir. Driver ve Car ikisinde de name bulunabilir; ama Driver is a Car anlamsızdır.
Kırılgan hiyerarşi ve MRO kavram radarı
Derin kalıtım zincirleri üst sınıftaki küçük değişikliklerin çok sayıda alt sınıfa yayılmasına yol açabilir. Bu derste iki-üç seviyeden daha derin hiyerarşiler tasarlamayacağız.
Python ayrıca çoklu kalıtıma izin verir:
class C(A, B):
passBu durumda aynı adlı davranışın hangi sırayla aranacağını method resolution order (MRO) belirler. C.mro() ile bu sıra görülebilir. Çoklu kalıtım ve MRO bu dersin uygulama/ölçme kapsamı değildir; yalnızca internette karşılaştığınızda terimi tanımanız beklenir.
İyi OOP tasarımı mümkün olduğunca çok hiyerarşi üretmek değildir. Kompozisyon çoğu durumda daha gevşek ve değiştirilebilir bir bağ kurar.
Alıştırma — Uygun ilişkiyi seç
Dog–Animal, Order–Customer, Laptop–Battery, Teacher–Course, AdminUser–User çiftlerinde is-a, has-a veya “ikisi de değil” seçin. is-a seçtiğiniz her durumda ayrıca “üst tür beklenen yerde alt tür güvenle kullanılabilir mi?” sorusunu yanıtlayın.
Alıştırma — Override tamamla
return self.width * self.heightNotImplementedError burada “alt sınıf bu davranışı sağlamalı” beklentisini görünür kılan öğretim örneğidir; sınıfı teknik olarak soyut yapmaz. 12. haftada NotImplemented ile NotImplementedError arasındaki kritik farkı ayrıca göreceğiz.
Alıştırma — Normal metotta super() kullan
Bir Logger.log(message) metodu "LOG: ..." döndürsün. TimestampLogger, log() metodunu override etsin; önce super().log(message) çağırıp sonra sonuca " [zaman damgalı]" eklesin. Üst metodu kopyalamadan davranışı genişletin.
Küçük üretim görevi — Ödeme türleri
Bir Payment üst sınıfı ile CardPayment ve CashPayment alt sınıflarını tasarlayın. Her ikisi pay(amount) sunsun. En az bir alt sınıfta super() ile normal bir üst metodu genişletin.
Çalışır kod teslimi: İki alt türü aynı listede tutup pay() çağrılarını çalıştırın; ayrıca isinstance(child, Parent) sonucunu assert ile doğrulayın. Bir geçersiz kalıtım örneği yazıp neden LSP açısından sorunlu olduğunu iki cümleyle açıklayın.
Kendinizi kontrol edin
- Kalıtım hangi ilişkiyi ifade etmelidir?
- Liskov yerine geçme ilkesinin bu dersteki temel sorusu nedir?
isinstance(dev, Employee)nedenTrueolabilir?- Override nedir?
super()normal bir metotta ne işe yarayabilir?- Ortak kod bulunması tek başına kalıtım gerekçesi midir?
- MRO hangi problemle ilgilidir?
Bu haftadan akılda kalması gerekenler
- Kalıtım bir
is-ailişkisidir; alt tür üst türün beklenen sözleşmesini korumalıdır. - Bu davranışsal beklenti Liskov yerine geçme ilkesiyle ilişkilidir.
- Alt sınıf davranışı miras alabilir, ekleyebilir veya override edebilir.
super()yalnızca kurucuda değil, normal davranışı genişletirken de kullanılabilir.- Alt sınıf örneği üst sınıf açısından da
isinstanceolabilir. - Çoklu kalıtımda MRO önemlidir; bu derste tanıma düzeyindedir.
- Kompozisyon her zaman gerçek bir alternatiftir.