🎯 0.4: Python Sınıflar ve Objeler

Algoritmalar ve Veri Yapıları Dersi - Object-Oriented Programming (OOP)

✅ Python yorumlayıcısı hazır! Kodları çalıştırabilirsiniz.

🌟 Nesne Yönelimli Programlama (OOP) Nedir?

Object-Oriented Programming (OOP), programlamayı gerçek dünya nesneleri gibi düşünerek organize etme yaklaşımıdır. Her nesne (obje) hem veri (özellikler) hem de davranış (metodlar) içerir.

🏗️ Sınıf ve Obje İlişkisi

graph TD A[Sınıf: Araba
Blueprint/Şablon] --> B[Obje 1: Kırmızı BMW] A --> C[Obje 2: Mavi Audi] A --> D[Obje 3: Siyah Mercedes] B --> B1[marka: BMW
renk: Kırmızı
hız: 0] C --> C1[marka: Audi
renk: Mavi
hız: 0] D --> D1[marka: Mercedes
renk: Siyah
hız: 0] style A fill:#f5576c,color:#fff style B fill:#28a745,color:#fff style C fill:#28a745,color:#fff style D fill:#28a745,color:#fff
🎯 Temel OOP Kavramları:
  • Sınıf (Class): Nesnelerin şablonu/taslağı. Bir nesnenin nasıl olacağını tanımlar
  • Obje/Nesne (Object): Sınıftan oluşturulan gerçek örnekler (instance)
  • Constructor (__init__): Obje oluşturulurken çalışan özel metod
  • self: Objenin kendisini temsil eden referans (Python'a özgü)
  • Instance Variable: Her objenin kendi verileri (özellikler)
  • Instance Method: Objenin davranışları (fonksiyonlar)

🌍 Gerçek Dünya

Araba:

  • Özellikler: Marka, model, renk, hız
  • Davranışlar: Hızlan, yavaşla, dur, dön

💻 Python'da

Araba Sınıfı:

  • Özellikler: Instance variables
  • Davranışlar: Instance methods

🔨 İlk Sınıfımızı Oluşturalım

Basit Bir Sınıf - Köpek

Python Kodu
class Kopek:
    """Köpek sınıfı - basit bir örnek"""
    
    # Constructor - obje oluşturulurken çalışır
    def __init__(self, isim, yas):
        self.isim = isim  # Instance variable
        self.yas = yas    # Instance variable
        print(f"Yeni bir köpek oluşturuldu: {isim}")
    
    # Instance method
    def havla(self):
        print(f"{self.isim}: Hav hav!")
    
    def bilgi_goster(self):
        print(f"İsim: {self.isim}, Yaş: {self.yas}")

# Obje oluşturma (instantiation)
kopek1 = Kopek("Karabaş", 3)
kopek2 = Kopek("Pamuk", 5)

print("\n--- Köpek 1 ---")
kopek1.bilgi_goster()
kopek1.havla()

print("\n--- Köpek 2 ---")
kopek2.bilgi_goster()
kopek2.havla()
⚡ Önemli Noktalar:
self: Metodların ilk parametresi her zaman self'tir. Objenin kendisini temsil eder.
__init__: Constructor metodu, obje oluşturulurken otomatik çalışır.
self.değişken: Instance variable tanımlaması. Her objenin kendi kopyası vardır.

📐 Pratik Örnek: Dikdörtgen Sınıfı

genişlik (w) yükseklik (h) Alan = w × h | Çevre = 2(w + h)
Python Kodu
class Dikdortgen:
    """Dikdörtgen sınıfı"""
    
    def __init__(self, genislik, yukseklik):
        """Constructor - dikdörtgen oluşturur"""
        self.genislik = genislik
        self.yukseklik = yukseklik
    
    def alan_hesapla(self):
        """Dikdörtgenin alanını hesaplar"""
        return self.genislik * self.yukseklik
    
    def cevre_hesapla(self):
        """Dikdörtgenin çevresini hesaplar"""
        return 2 * (self.genislik + self.yukseklik)
    
    def kare_mi(self):
        """Dikdörtgenin kare olup olmadığını kontrol eder"""
        return self.genislik == self.yukseklik
    
    def bilgi_yazdir(self):
        """Dikdörtgen bilgilerini yazdırır"""
        print(f"Dikdörtgen:")
        print(f"  Genişlik: {self.genislik}")
        print(f"  Yükseklik: {self.yukseklik}")
        print(f"  Alan: {self.alan_hesapla()}")
        print(f"  Çevre: {self.cevre_hesapla()}")
        print(f"  Kare mi? {'Evet' if self.kare_mi() else 'Hayır'}")

# Dikdörtgen objeleri oluştur
dikdortgen1 = Dikdortgen(5, 10)
dikdortgen2 = Dikdortgen(7, 7)

print("=== Dikdörtgen 1 ===")
dikdortgen1.bilgi_yazdir()

print("\n=== Dikdörtgen 2 ===")
dikdortgen2.bilgi_yazdir()

🔢 Kesir Sınıfı

Matematiksel kesir (oran) işlemlerini yapan bir sınıf yazalım:

3 4 + 2 5 = 23 20 pay/payda Kesirler ile toplama, çıkarma, çarpma, bölme
Python Kodu
def ebob_hesapla(a, b):
    """En Büyük Ortak Bölen (Öklid algoritması)"""
    while b:
        a, b = b, a % b
    return a

class Kesir:
    """Matematiksel kesir sınıfı"""
    
    def __init__(self, pay, payda):
        """Kesir oluştur"""
        if payda == 0:
            print("HATA: Payda sıfır olamaz!")
            self.pay = 0
            self.payda = 1
        else:
            self.pay = pay
            self.payda = payda
            self.sadelestir()
    
    def sadelestir(self):
        """Kesri sadeleştirir (EBOB ile)"""
        ebob = ebob_hesapla(abs(self.pay), abs(self.payda))
        self.pay //= ebob
        self.payda //= ebob
        
        # Payda negatifse işareti paya taşı
        if self.payda < 0:
            self.pay = -self.pay
            self.payda = -self.payda
    
    def goster(self):
        """Kesri string olarak döndürür"""
        if self.payda == 1:
            return str(self.pay)
        return f"{self.pay}/{self.payda}"
    
    def ondalik(self):
        """Kesrin ondalık değerini döndürür"""
        return self.pay / self.payda
    
    def topla(self, diger):
        """İki kesri toplar"""
        yeni_pay = self.pay * diger.payda + diger.pay * self.payda
        yeni_payda = self.payda * diger.payda
        return Kesir(yeni_pay, yeni_payda)
    
    def cikar(self, diger):
        """İki kesri çıkarır"""
        yeni_pay = self.pay * diger.payda - diger.pay * self.payda
        yeni_payda = self.payda * diger.payda
        return Kesir(yeni_pay, yeni_payda)
    
    def carp(self, diger):
        """İki kesri çarpar"""
        yeni_pay = self.pay * diger.pay
        yeni_payda = self.payda * diger.payda
        return Kesir(yeni_pay, yeni_payda)
    
    def bol(self, diger):
        """Birinci kesri ikinciye böler"""
        yeni_pay = self.pay * diger.payda
        yeni_payda = self.payda * diger.pay
        return Kesir(yeni_pay, yeni_payda)

# Kesir objeleri oluştur
k1 = Kesir(3, 4)
k2 = Kesir(2, 5)
k3 = Kesir(6, 8)  # Sadeleştirilecek -> 3/4

print("Kesir Örnekleri:")
print(f"k1 = {k1.goster()} = {k1.ondalik():.4f}")
print(f"k2 = {k2.goster()} = {k2.ondalik():.4f}")
print(f"k3 = {k3.goster()} (6/8 sadeleştirildi)")

# İşlemler
print("\n=== İşlemler ===")
toplam = k1.topla(k2)
print(f"{k1.goster()} + {k2.goster()} = {toplam.goster()}")

fark = k1.cikar(k2)
print(f"{k1.goster()} - {k2.goster()} = {fark.goster()}")

carpim = k1.carp(k2)
print(f"{k1.goster()} × {k2.goster()} = {carpim.goster()}")

bolum = k1.bol(k2)
print(f"{k1.goster()} ÷ {k2.goster()} = {bolum.goster()}")

# Zincirleme işlem
k4 = Kesir(1, 2)
k5 = Kesir(1, 3)
k6 = Kesir(1, 6)
sonuc = k4.topla(k5).topla(k6)
print(f"\n1/2 + 1/3 + 1/6 = {sonuc.goster()}")
✅ Kesir Sınıfının Özellikleri:
  • Otomatik sadeleştirme (EBOB kullanarak)
  • Dört işlem: toplama, çıkarma, çarpma, bölme
  • Ondalık değer hesaplama
  • Zincirleme işlem desteği (method chaining)
  • Payda sıfır kontrolü

△ Üçgen Sınıfı

a b c Çevre = a + b + c Alan = √[s(s-a)(s-b)(s-c)] (Heron)
Python Kodu
class Ucgen:
    """Üçgen sınıfı - üç kenar uzunluğu ile tanımlanır"""
    
    def __init__(self, a, b, c):
        """Üçgen oluştur"""
        self.a = a
        self.b = b
        self.c = c
        
        if not self.gecerli_mi():
            print("UYARI: Bu kenar uzunlukları geçerli bir üçgen oluşturmaz!")
    
    def gecerli_mi(self):
        """Üçgen eşitsizliğini kontrol eder"""
        return (self.a + self.b > self.c and 
                self.a + self.c > self.b and 
                self.b + self.c > self.a)
    
    def cevre(self):
        """Üçgenin çevresini hesaplar"""
        return self.a + self.b + self.c
    
    def alan(self):
        """Üçgenin alanını hesaplar (Heron formülü)"""
        if not self.gecerli_mi():
            return 0
        
        s = self.cevre() / 2
        alan = (s * (s - self.a) * (s - self.b) * (s - self.c)) ** 0.5
        return alan
    
    def dik_mi(self):
        """Üçgenin dik olup olmadığını kontrol eder"""
        kenarlar = sorted([self.a, self.b, self.c])
        return abs(kenarlar[0]**2 + kenarlar[1]**2 - kenarlar[2]**2) < 0.0001
    
    def bilgi_yazdir(self):
        """Üçgen bilgilerini yazdırır"""
        print(f"Üçgen Kenarları: a={self.a}, b={self.b}, c={self.c}")
        if self.gecerli_mi():
            print(f"Çevre: {self.cevre():.2f}")
            print(f"Alan: {self.alan():.2f}")
            print(f"Dik üçgen mi? {'Evet' if self.dik_mi() else 'Hayır'}")

# Test
print("=== Dik Üçgen (3-4-5) ===")
ucgen1 = Ucgen(3, 4, 5)
ucgen1.bilgi_yazdir()

print("\n=== Normal Üçgen ===")
ucgen2 = Ucgen(7, 8, 9)
ucgen2.bilgi_yazdir()

🎓 Öğrenci Bilgi Sistemi

Python Kodu
class Ogrenci:
    """Öğrenci bilgi sistemi sınıfı"""
    
    # Class variable - tüm öğrenciler için ortak
    okul_adi = "Algoritma Üniversitesi"
    
    def __init__(self, ad, soyad, numara):
        """Öğrenci oluştur"""
        self.ad = ad
        self.soyad = soyad
        self.numara = numara
        self.notlar = []
    
    def not_ekle(self, ders, not_degeri):
        """Öğrenciye not ekler"""
        if 0 <= not_degeri <= 100:
            self.notlar.append({'ders': ders, 'not': not_degeri})
            print(f"✓ {ders}: {not_degeri} eklendi")
        else:
            print("❌ Not 0-100 arasında olmalı!")
    
    def ortalama(self):
        """Not ortalamasını hesaplar"""
        if len(self.notlar) == 0:
            return 0
        toplam = sum(n['not'] for n in self.notlar)
        return toplam / len(self.notlar)
    
    def rapor(self):
        """Öğrenci raporunu gösterir"""
        print("=" * 50)
        print(f"ÖĞRENCI RAPORU - {Ogrenci.okul_adi}")
        print("=" * 50)
        print(f"Ad Soyad: {self.ad} {self.soyad}")
        print(f"Numara: {self.numara}")
        print("-" * 50)
        for n in self.notlar:
            print(f"  {n['ders']}: {n['not']}")
        print("-" * 50)
        if len(self.notlar) > 0:
            print(f"Ortalama: {self.ortalama():.2f}")
        print("=" * 50)

# Test
ogrenci1 = Ogrenci("Ahmet", "Yılmaz", "2021001")
ogrenci1.not_ekle("Algoritmalar", 85)
ogrenci1.not_ekle("Veri Yapıları", 92)
ogrenci1.not_ekle("Veritabanı", 78)

print()
ogrenci1.rapor()

🏦 Pratik Örnek: Banka Hesabı

stateDiagram-v2 [*] --> HesapAçıldı: Yeni Hesap HesapAçıldı --> ParaYatır: para_yatir() ParaYatır --> ParaÇek: para_cek() ParaÇek --> ParaYatır: para_yatir() ParaYatır --> [*]: Hesap Kapatıldı ParaÇek --> [*]: Hesap Kapatıldı
Python Kodu
class BankaHesabi:
    """Basit banka hesabı sınıfı"""
    
    def __init__(self, hesap_sahibi, bakiye=0):
        """Banka hesabı oluştur"""
        self.hesap_sahibi = hesap_sahibi
        self.bakiye = bakiye
        print(f"✓ Hesap oluşturuldu: {hesap_sahibi}")
    
    def para_yatir(self, miktar):
        """Hesaba para yatırır"""
        if miktar <= 0:
            print("❌ Miktar pozitif olmalı!")
            return False
        
        self.bakiye += miktar
        print(f"✓ {miktar} TL yatırıldı. Yeni bakiye: {self.bakiye} TL")
        return True
    
    def para_cek(self, miktar):
        """Hesaptan para çeker"""
        if miktar <= 0:
            print("❌ Miktar pozitif olmalı!")
            return False
        
        if miktar > self.bakiye:
            print(f"❌ Yetersiz bakiye! Mevcut: {self.bakiye} TL")
            return False
        
        self.bakiye -= miktar
        print(f"✓ {miktar} TL çekildi. Yeni bakiye: {self.bakiye} TL")
        return True
    
    def bakiye_goster(self):
        """Bakiyeyi gösterir"""
        print(f"{self.hesap_sahibi} - Bakiye: {self.bakiye} TL")

# Test
hesap1 = BankaHesabi("Ahmet Yılmaz", 1000)
print()

hesap1.bakiye_goster()
print()

hesap1.para_yatir(500)
hesap1.para_cek(200)
print()

hesap1.para_cek(5000)  # Yetersiz bakiye
print()

hesap1.bakiye_goster()

⚖️ Fonksiyon vs Sınıf: Ne Zaman Hangisi?

📚 Fonksiyonlar

Ne zaman?
  • Tekil işlemler
  • Veri saklama gereği yok
  • Basit hesaplamalar
Örnek:
def topla(a, b):
    return a + b

🎯 Sınıflar

Ne zaman?
  • Veri + fonksiyon birlikte
  • Durum saklamak gerekli
  • Birden fazla obje
Örnek:
class Hesap:
    def __init__(self, bakiye):
        self.bakiye = bakiye

📝 Kendiniz Deneyin!

Aşağıdaki kod alanını düzenleyebilir ve kendi kodlarınızı yazabilirsiniz:

Düzenlenebilir Python Kodu