Nesne Yönelimli Programlama (OOP): Sınıflar, Miras ve Kapsülleme — Python Örnekü
Programlama Paradigmaları
Nesne Yönelimli Programlama (OOP): Sınıflar, Miras ve Kapsülleme — Python Örnekü

Giriş
Nesne yönelimli programlama (OOP), verileri ve bu verilerle ilgili davranışları bir arada tutan nesneler etrafında kod yazma yaklaşımıdır. Bu yaklaşım, kodun daha modüler, yeniden kullanılabilir ve bakımının daha kolay olmasını hedefler. OOP'nin temel ilkeleri ve Python özelinde uygulama biçimleriyle ilgili genel bir çerçeve için resmi dokümantasyon ve derleyici rehberleri yol göstericidir; örneğin IBM'in OOP tanımları başlangıç için faydalı bir özet sunar (IBM dokümantasyonu).
Sınıflar ve nesneler — Temel kavramlar
Sınıf (class) bir nesnenin şablonu; nesneler ise bu şablondan oluşturulan örneklerdir (instances). Sınıf içinde özellikler (attributes) ve metotlar (methods) tanımlanır. Python, sınıfları ve nesneleri doğal olarak destekler ve hem basit hem de karmaşık uygulamalarda OOP'yi kullanmaya uygundur (Python dersleri örneği).
Basit bir örnek — Circle:
class Circle:
pi = 3.14159
def __init__(self, radius):
self.radius = radius
def area(self):
return Circle.pi * self.radius ** 2
@classmethod
def from_diameter(cls, diameter):
return cls(diameter / 2)
@staticmethod
def is_positive(value):
return value > 0
Yukarıdaki örnekte pi sınıf değişkeni, __init__ kurucu metodu, bir örnek metodu area, sınıf metodu from_diameter ve yardımcı statik metot is_positive görülebilir.
Kapsülleme (Encapsulation)
Kapsülleme, bir nesnenin iç durumunu dışa kapatarak (veya sınırlandırarak) arayüz üzerinden erişim sağlamaya yönelik yaklaşımdır. Python'da gerçek anlamda erişim engelleme mekanizması yoktur; bunun yerine iki yaklaşım yaygındır:
- Tek alt çizgi (_name): koruma niyetini gösterir, ancak erişim engellenmez.
- Çift alt çizgi (__name): isim değiştirme (name mangling) ile dışarıdan doğrudan erişimi zorlaştırır.
Örnek — BankAccount:
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.__balance = balance # private via name mangling
def deposit(self, amount):
if amount > 0:
self.__balance += amount
else:
raise ValueError("Miktar pozitif olmalı")
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
return amount
raise ValueError("Yetersiz bakiye veya geçersiz miktar")
def get_balance(self):
return self.__balance
Alternatif olarak @property dekoratörü ile kontrol edilen erişim sağlayabilirsiniz:
Örnek — Person (getter/setter):
class Person:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not value:
raise ValueError("İsim boş olamaz")
self._name = value
Miras (Inheritance)
Miras, bir sınıfın başka bir sınıftan özellik ve metotları devralmasını sağlar; böylece ortak davranışlar üst sınıfta toplanabilir. Ancak miras kullanımı tasarım gereksinimine bağlı olmalı; her zaman en iyi çözüm olmayabilir. Bir üst sınıf-sub sınıf ilişkisinin gerçekten "is-a" (bir ...dır) ilişkisini temsil edip etmediğini değerlendirin.
Örnek — Animal, Dog, Cat:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("Subclass speak implement etmeli")
class Dog(Animal):
def speak(self):
return "Hav"
class Cat(Animal):
def speak(self):
return "Miyav"
Alt sınıflar üst sınıftaki metotları ezebilir (override) ve super() ile üst sınıfın kurucusunu çağırabilirler. Bu örnek mirasın kod tekrarını azaltırken, polimorfizmle birlikte esneklik sağlar.
Polimorfizm (Polymorphism) ve Duck Typing
Polimorfizm, farklı sınıfların aynı arayüzü (metot adını) kendi ihtiyaçlarına göre farklı şekilde uygulayabilmesidir. Python'da "duck typing" yaklaşımı nedeniyle nesnelerin türüne sıkı şekilde bağlı kalmadan, gerekli metot mevcutsa nesneyi kullanabilirsiniz.
Örnek — Polimorfik kullanım:
animals = [Dog("Karabas"), Cat("Minnoş")]
for a in animals:
print(a.name, "->", a.speak())
Pratik örnek: Küçük bir uygulama taslağı
Aşağıda miras ve polimorfizmi birleştiren basit bir şekil (shape) örneği var:
class Shape:
def area(self):
raise NotImplementedError
class Rectangle(Shape):
def __init__(self, w, h):
self.w = w
self.h = h
def area(self):
return self.w * self.h
class Circle(Shape):
def __init__(self, r):
self.r = r
def area(self):
return 3.14159 * self.r ** 2
shapes = [Rectangle(2, 3), Circle(1)]
for s in shapes:
print(s.area())
Bu yapı OOP'nin test edilebilirlik ve genişletilebilirlik avantajlarını göstermeye yöneliktir: yeni bir şekil eklemek için Shape'i genişletmeniz yeterlidir.
Nasıl başlayabilirsiniz? Adım adım rehber
- Problemi parçalayın: hangi veri ve davranışları gruplayacağınıza karar verin.
- Sınıfları tanımlayın: her sınıfın sorumluluğunu kısa bir cümleyle belirleyin (Single Responsibility).
- Kurucu (__init__) ve gerekli metotları yazın; iç durumları kapsülleyin.
- Miras kullanacaksanız "is-a" ilişkisini doğrulayın; aksi halde kompozisyonu tercih edin.
- Birim testleri (unit tests) ile davranışı doğrulayın; küçük, izole testler yazın.
- Tip ipuçları (type hints) ve dokümantasyon ile okunabilirliği artırın.
İyi uygulamalar ve yaygın tuzaklar
- İyi: Küçük, tek sorumluluğu olan sınıflar; kötü: çok fazla sorumluluk veren büyük sınıflar.
- İyi: Kompozisyonu düşünmek (bir sınıf başka bir sınıfı kullanır). Kötü: mirası gereksiz yere kullanmak.
- İyi: Açık arayüzler ve testler; Kötü: özel alanlara doğrudan erişim ve sıkı bağımlılıklar.
- Dokümantasyon ve tip ipuçları (PEP 8, PEP 484) projede sürekliliği sağlar.
Kaynaklar ve ileri okuma
- IBM — Nesne yönelimli programlama açıklaması (genel kavramlar).
- Hands-on Mentor — Python'da OOP kavramları ve uygulamalar (uygulamalı örnekler).
- Hanuce — Python dersleri (sınıflar ve Python sözdizimi örnekleri).
Kapanış
OOP, doğru uygulandığında projeyi daha sürdürülebilir hale getirir. Python özgürlüğü ve esnekliği sayesinde OOP kavramlarını öğrenecek ve küçük projelerle uygulayarak pekiştireceksiniz. Öğrendiklerinizi küçük adımlarla (ör. bir adres defteri, basit banka hesabı, şekil kütüphanesi) uygulamaya koymak faydalıdır.
Not: Bu makalede verilen kod örnekleri eğitim amaçlıdır. Gerçek dünyada çoklu iş parçacığı, performans, hata yönetimi gibi konular ek kontrol ve tasarım gerektirebilir. Daha derin uygulamalar ve en iyi uygulamalar için ek kaynaklara ve resmi dokümantasyona başvurun.