Algoritmalar ve Veri Yapıları Dersi - Object-Oriented Programming (OOP)
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.
Bir banka uygulaması yazıyorsun ve 1000 müşteri hesabını yönetmen gerekiyor...
# Her hesap için ayrı değişkenler 😱
hesap1_sahibi = "Ali"
hesap1_bakiye = 1000
hesap1_hesap_no = "TR001"
hesap2_sahibi = "Ayşe"
hesap2_bakiye = 2500
hesap2_hesap_no = "TR002"
# Para çekme işlemi - her hesap için ayrı!
def hesap1_para_cek(miktar):
global hesap1_bakiye
if hesap1_bakiye >= miktar:
hesap1_bakiye -= miktar
def hesap2_para_cek(miktar):
global hesap2_bakiye
if hesap2_bakiye >= miktar:
hesap2_bakiye -= miktar
# 1000 müşteri = 1000 fonksiyon??? 🤯
⚠️ Sorunlar:
class BankaHesabi:
def __init__(self, sahibi, bakiye):
self.sahibi = sahibi
self.bakiye = bakiye
def para_cek(self, miktar):
if self.bakiye >= miktar:
self.bakiye -= miktar
return True
return False
# Şimdi istediğin kadar hesap oluştur!
hesap1 = BankaHesabi("Ali", 1000)
hesap2 = BankaHesabi("Ayşe", 2500)
hesap3 = BankaHesabi("Mehmet", 5000)
# Hepsi aynı metodları kullanır
hesap1.para_cek(200)
hesap2.para_cek(500)
# 1000 müşteri? Sadece 1000 obje! ✨
✅ Avantajlar:
Sınıf = Kurabiye kalıbı 🍪 | Obje = O kalıpla yapılan kurabiyeler
Nesne yönelimli programlamanın temelini oluşturan dört prensip:
Veri ve metodları bir arada tutma. Dışarıdan erişimi kontrol etme.
class Hesap:
def __init__(self):
self.__bakiye = 0 # Gizli!
def bakiye_goster(self):
return self.__bakiye
Karmaşık detayları gizleyip, sadece gerekli arayüzü sunma.
# Kullanıcı sadece bunu görür:
araba.calistir()
# Motor, akü, yakıt sistemi...
# detayları gizli kalır
Bir sınıfın özelliklerini başka sınıflara aktarma.
class Hayvan:
def ses_cikar(self): pass
class Kopek(Hayvan):
def ses_cikar(self):
print("Hav hav!")
Aynı metodun farklı sınıflarda farklı davranması.
def ses_cikardir(hayvan):
hayvan.ses_cikar()
ses_cikardir(kopek) # Hav hav!
ses_cikardir(kedi) # Miyav!
Araba:
Araba Sınıfı:
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()
self'tir. Objenin kendisini temsil eder.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()
Matematiksel kesir (oran) işlemlerini yapan bir sınıf yazalım:
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()}")
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()
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()
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()
Bu en çok sorulan sorulardan biri! İşte karar vermenize yardımcı olacak pratik kurallar:
# ✅ Fonksiyon için uygun
def faktoriyel(n):
return 1 if n <= 1 else n * faktoriyel(n-1)
def ortalama_bul(liste):
return sum(liste) / len(liste)
def metin_temizle(metin):
return metin.strip().lower()
# ✅ Sınıf için uygun
class Ogrenci:
def __init__(self, ad, notlar):
self.ad = ad
self.notlar = notlar # durum!
def ortalama(self):
return sum(self.notlar) / len(self.notlar)
def not_ekle(self, yeni_not):
self.notlar.append(yeni_not) # durum değişir!
# Her karakter için ayrı değişken
karakter1_isim = "Savaşçı"
karakter1_can = 100
karakter1_guc = 50
karakter2_isim = "Büyücü"
karakter2_can = 70
karakter2_guc = 80
def karakter1_saldir():
# karakter2'ye zarar ver
pass
# Karmaşık ve yönetilemez!
class Karakter:
def __init__(self, isim, can, guc):
self.isim = isim
self.can = can
self.guc = guc
def saldir(self, hedef):
hedef.can -= self.guc
print(f"{self.isim} saldırdı!")
k1 = Karakter("Savaşçı", 100, 50)
k2 = Karakter("Büyücü", 70, 80)
k1.saldir(k2) # Temiz ve anlaşılır!
"Veri + O veriye yapılan işlemler" birlikte geziyorsa → Sınıf
"Girdi → İşlem → Çıktı" tek seferlik ise → Fonksiyon