Kalıtım II — super() & Metot Ezme (override)
Geçen hafta SayacButonu(QPushButton) türettik: devraldık + yeni
metotlar ekledik. Bu hafta var olan metotları ezip davranışını değiştireceğiz.
Atanın gücüne eriş; kurucusunu ve metotlarını çağır.
Devralınan metodu yeniden tanımla; ez ya da genişlet.
Python metodu hangi sırayla bulur? Çoklu kalıtım.
Sonunda: SayacButonu'nu ezerek akıllı buton
ailesi yapacağız.
super() nedir?super(), bir sınıfın atasına (üst sınıfına)
erişmenin yoludur. "Bu işi atam nasıl yapıyordu, ona sor" demektir.
class SayacButonu(QPushButton):
def __init__(self):
super().__init__() # QPushButton kurucusu
self.sayac = 0 # sonra kendi işini yap
Bunu Hafta 1'den beri yazıyorduk — artık ne yaptığını tam biliyoruz.
super() Aynı Nesne, Üst Sınıf Gözüyleselfsuper() yeni bir nesne oluşturmaz; aynı nesnenin ata sürümüne bakar.
Atanın metodunu bulup çalıştırır — MRO zincirinde bir üst durak.
QPushButton.__init__(self) yerine super() — ata değişse bile çalışır.
super().artir() = "aynı ben, ama atamın
artir'ını çalıştır."
super().__init__() Şart?class SayacButonu(QPushButton):
def __init__(self):
self.sayac = 0 # 💥 super() UNUTULDU
self.setText("Tıkla") # RuntimeError: base __init__ çağrılmadı
Kendi __init__'ini yazan çocuk, ilk iş super().__init__()
çağırmalı — yoksa QPushButton'ın altyapısı hiç kurulmaz.
Sonuç: RuntimeError ya da yarım/garip
davranan bir widget.
class Hayvan:
def __init__(self, ad):
self.ad = ad
class Kedi(Hayvan):
def __init__(self, ad, renk):
super().__init__(ad) # ad'ı ataya GEÇİR (o kursun)
self.renk = renk # kalanı kendin
k = Kedi("Tekir", "sarı") # k.ad="Tekir", k.renk="sarı"
Ata bir argüman bekliyorsa (ad), onu super().__init__(ad) ile
iletirsin.
İş bölümü: ortak kısmı ata kurar, farkı çocuk ekler.
Çocuk, atanın metodunu olduğu gibi kullanır.
Çocuk, aynı isimli metodu yeniden tanımlar → kendi sürümü çalışır, atanınki gölgelenir.
Aynı isim, farklı gövde. Çocuğun sürümü atanınkinin yerini alır (o nesne için).
class Ata:
def selam(self): print("Ata selamı")
class Cocuk(Ata):
def selam(self): print("Çocuk selamı") # aynı isim → EZME
Cocuk().selam() # "Çocuk selamı" (önce çocuğa bakar)
Ata().selam() # "Ata selamı" (ata değişmedi)
Python metodu nesnenin sınıfından başlayıp yukarı doğru arar. İlk bulduğunu çalıştırır.
Çocukta varsa → çocuğunki. Ezme budur.
class RenkliButon(SayacButonu): # SayacButonu'ndan türe
def artir(self): # aynı isim → EZME (override)
super().artir() # önce atanın işi: say + güncelle
if self.sayac >= 5: # sonra KENDİ eklememiz:
self.setStyleSheet("background:#ef4444") # kırmızıya dön
super().artir() # ata: say
if self.sayac >= 5: kırmızı
Tıkla: super().artir() saymayı sürdürür (ata), 5'ten sonra
bizim eklediğimiz satır butonu kırmızıya çevirir. Ezme + super() = genişletme.
def artir(self):
self.setText("değişti") # atanınki YOK sayıldı
super() çağırmazsan atanın davranışı kaybolur.
def artir(self):
super().artir() # atanınki +
self.renklendir() # kendi eklemen
super() ile atanın işini korur, üstüne eklersin.
En sık kalıp: metodu ez, içinde super() çağır, sonra kendi farkını ekle.
def artir(self):
super().artir() # ata: say
if self.sayac >= 5:
self.kirmizi()
✅ Genişletme — sayar ve renklenir. (0 tık)
def artir(self):
# super() YOK!
self.setText("değişti")
⚠️ Değiştirme — sayma kayboldu. (hep "değişti")
Sol biriktirir, sağ atanın saymasını yok sayar. Fark: super().artir()
çağrısı.
def artir(self):
super().artir() # 1) atanın işini yaptır
if self.sayac >= 5: # 2) kendi koşulun
self.setStyleSheet("background:#ef4444") # 3) kendi eklemen
Aynı isimli metodu yeniden yaz.
Atanın işini silmeden yaptır.
Kendi farkını üstüne koy.
artir()'ıyla aynı isimli metot yazarsan?btn.artir() çağrılınca Python metodu şu sırayla arar:
RenkliButon
1. çocuk
SayacButonu
2. ata
QPushButton
3. dede
QWidget…
yukarı
İlk bulduğu metodu çalıştırır. super() tam da bu
zincirde "bir sonrakine" gitmektir.
RenkliButon.mro()
# [RenkliButon, SayacButonu, QPushButton,
# QAbstractButton, QWidget, QObject, …, object]
Sınıf.mro() (ya da Sınıf.__mro__) o sınıfın arama sırasını liste
olarak verir.
En sonda hep object vardır. (Araya bazı Qt iç sınıfları da girer; kısalttık.)
class Ucan:
def hareket(self): print("uçar")
class Yuzen:
def hareket(self): print("yüzer")
class DenizUcagi(Ucan, Yuzen): # iki atadan
pass
DenizUcagi().hareket() # uçar (soldan sağa)
Bir sınıf birden çok atadan türeyebilir. Çakışma olursa MRO karar verir — soldaki önce gelir.
class C(A, B): önce A'ya bakılır.
class LoglamaMixin: # yalnız yetenek katar
def logla(self):
print(self.text(), "tıklandı")
class LoglayanButon(LoglamaMixin, SayacButonu):
def artir(self):
super().artir() # atanın işi
self.logla() # mixin yeteneği
Mixin = tek başına anlamlı olmayan, başka sınıflara yetenek katan küçük sınıf.
Qt uygulamalarında sık kullanılır (loglama, kaydetme…).
class SayacButonu(QPushButton):
def mousePressEvent(self, olay): # Qt metodunu EZ
print("basıldı!") # kendi eklemen
super().mousePressEvent(olay) # Qt'nin işini de yap
Override'ın asıl gücü: Qt'nin hazır olay metotlarını (fare, tuş, çizim) ezip kendi davranışını eklemek.
Yine kural: super() çağır ki Qt'nin normal
işleyişi bozulmasın.
class C(A, B) — çakışan calis() hangisi çalışır?Override'da atanın işini istemeden silmek — sayma/çizim kaybolur.
Override içinde super() yerine self.artir()
→ sonsuz döngü (kendini çağırır).
Ezmek istediğin metodun adını yanlış yazmak → ezme olmaz, yeni bir metot doğar.
Kural: ataya erişmek için her zaman super(),
asla self.
✅ super() = aynı nesne, atanın gözüyle
✅ super().__init__(arg) — ataya argüman geçir
✅ Ezme (override): aynı isim → çocuk kazanır
✅ Genişletme = override + super() + ekle
✅ MRO zinciri, Sınıf.mro(), çoklu kalıtım
✅ Mixin + Qt olay metotlarını ezme
Geçen haftaki SayacButonu'nu ezerek farklı davranan üç buton
türet ve bir panele diz.
class SayacButonu(QPushButton): # geçen hafta
def __init__(self):
super().__init__()
self.sayac = 0
self.clicked.connect(self.artir)
self.setText("Tıkla (0)")
def artir(self):
self.sayac += 1
self.setText(f"Tıkla ({self.sayac})")
# Görev: artir()'ı ezerek 3 farklı buton yap.
Üç ezilmiş buton: RenkliButon (5'te kırmızı), CiftButon (2'şer artar), LimitliButon (10'da durur).
Süre: ~40 dk.
artir()'ı ez:
super().artir() + 5'te setStyleSheet.
artir()'ı ez:
super().artir()'ı iki kez çağır (2'şer say).
artir()'ı ez:
yalnızca sayac < 10 ise super().artir().
Üçünü bir QVBoxLayout'a
diz, if __name__ ile çalıştır.
✅ Kontrol: Üçü de super() kullanıyor mu? Sayma
mantığını hiçbiri sıfırdan yazmamalı.
Bir butonda
mousePressEvent'i ez; sağ tık ile sayacı sıfırlasın (super() unutma).
LoglamaMixin yaz; her
tıklamayı konsola yazan bir LoglayanButon üret.
Butonlarından birinin
.mro()'sunu yazdır; zinciri incele.
Bu görevler polimorfizmin (gelecek hafta) zeminini
hazırlıyor: aynı artir(), farklı davranışlar.
"Aynı çağrı, farklı davranış." Ezdiğimiz metotlar sayesinde farklı buton türleri aynı arayüzle ama kendince tepki verecek.