Logo
super() override __init__ MRO Ata ez genişlet Çocuk
İleri Programlama · Hafta 03

Metodu Ezelim mi,
Genişletelim mi?

Kalıtım II — super() & Metot Ezme (override)

▌super().__init__()  # atanın gücünü çağır
Bu Hafta

Butonu Türettik — Şimdi Onu Değiştirelim

Geçen hafta SayacButonu(QPushButton) türettik: devraldık + yeni metotlar ekledik. Bu hafta var olan metotları ezip davranışını değiştireceğiz.

1 · super()

Atanın gücüne eriş; kurucusunu ve metotlarını çağır.

2 · Ezme (override)

Devralınan metodu yeniden tanımla; ez ya da genişlet.

3 · MRO

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.

Altında Ne Var?

super() Aynı Nesne, Üst Sınıf Gözüyle

🎯 Aynı self

super() yeni bir nesne oluşturmaz; aynı nesnenin ata sürümüne bakar.

⛓️ Zincirde bir sonraki

Atanın metodunu bulup çalıştırır — MRO zincirinde bir üst durak.

🚫 İsim yazmaz

QPushButton.__init__(self) yerine super() — ata değişse bile çalışır.

super().artir() = "aynı ben, ama atamın artir'ını çalıştır."

Kurucu · 1/2

Neden 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.

Kurucu · 2/2

Ataya Argüman Geçirmek

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.

Metot Ezme (Override)

🧬 Devralma

Çocuk, atanın metodunu olduğu gibi kullanır.

✍️ Ezme (Override)

Ç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).

Python Nasıl Seçer

Önce Çocuğa Bakar

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.

Örnek · 1/2

Butona Renk Davranışı Ekle

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
5'ten sonra ↓
RenkliButon
Kırmızı buton
Örnek · 2/2 · Canlı 5'e gelince rengi değişir

Ezilmiş Davranışı Çalıştır

# RenkliButon.artir():
super().artir() # ata: say if self.sayac >= 5: kırmızı
Sayı: 0 · Eşik: 5
RenkliButon — canlı

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.

Ezme mi, Genişletme mi?

🔁 Tamamen Değiştir

def artir(self):
    self.setText("değişti")   # atanınki YOK sayıldı

super() çağırmazsan atanın davranışı kaybolur.

➕ Koru + Ekle (genişlet)

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.

super() İle mi, Olmadan mı? · Canlı İki butona da bas — farkı gör

Atanın İşi Korunur mu, Kaybolur mu?

def artir(self):
    super().artir()      # ata: say
    if self.sayac >= 5:
        self.kirmizi()
super() ile

✅ Genişletme — sayar ve renklenir. (0 tık)

def artir(self):
    # super() YOK!
    self.setText("değişti")
super()'siz

⚠️ Değiştirme — sayma kayboldu. (hep "değişti")

Sol biriktirir, sağ atanın saymasını yok sayar. Fark: super().artir() çağrısı.

Altın Kalıp

Genişletmenin Üç Adımı

    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

1 · Devral & Ez

Aynı isimli metodu yeniden yaz.

2 · super() Çağır

Atanın işini silmeden yaptır.

3 · Ekle

Kendi farkını üstüne koy.

Mini Quiz · 1/2

super() & Override

1) Atanın artir()'ıyla aynı isimli metot yazarsan?
2) Override'da atanınkini korumak için ne yazarsın?
Python Nasıl Bulur

Metot Çözümleme Sırası (MRO)

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.

Kanıt

MRO'yu Kendi Gözünle Gör

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.)

İki Ata

Çoklu Kalıtım

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.

Pratik Kullanım

Mixin: Yetenek Ekleme Sınıfı

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…).

Gerçek Güç

Qt'nin Kendi Metotlarını Ez

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.

Mini Quiz · 2/2

MRO & Çoklu Kalıtım

1) class C(A, B) — çakışan calis() hangisi çalışır?
2) Bir sınıfın metot arama sırasını nasıl görürsün?
Dikkat

Sık Yapılan Hatalar

😱 super() unutmak

Override'da atanın işini istemeden silmek — sayma/çizim kaybolur.

♾️ self.metot() çağırmak

Override içinde super() yerine self.artir() → sonsuz döngü (kendini çağırır).

🔤 İsim tutmaması

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.

Bu Hafta Ne Öğrendik?

✅ 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

Ders Sonu Uygulama · Proje

Proje: Akıllı Buton Ailesi

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.

🎯 Hedef

Üç ezilmiş buton: RenkliButon (5'te kırmızı), CiftButon (2'şer artar), LimitliButon (10'da durur).

Süre: ~40 dk.

Adım Adım

Nasıl İlerleyeceksin?

1 · RenkliButon

artir()'ı ez: super().artir() + 5'te setStyleSheet.

2 · CiftButon

artir()'ı ez: super().artir()'ı iki kez çağır (2'şer say).

3 · LimitliButon

artir()'ı ez: yalnızca sayac < 10 ise super().artir().

4 · Panel

Üçü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ı.

İleri Görevler

Erken Bitirdiysen

⭐ mousePressEvent

Bir butonda mousePressEvent'i ez; sağ tık ile sayacı sıfırlasın (super() unutma).

⭐⭐ Mixin

LoglamaMixin yaz; her tıklamayı konsola yazan bir LoglayanButon üret.

⭐⭐⭐ mro()

Butonlarından birinin .mro()'sunu yazdır; zinciri incele.

Bu görevler polimorfizmin (gelecek hafta) zeminini hazırlıyor: aynı artir(), farklı davranışlar.

Sonraki Hafta

Polimorfizm

"Aynı çağrı, farklı davranış." Ezdiğimiz metotlar sayesinde farklı buton türleri aynı arayüzle ama kendince tepki verecek.