Kompozisyon ve Kalıtım
Coddy'nin Python Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 37 / 64.
Nesne yönelimli programlama, kodun yeniden kullanımı için iki ana yaklaşım sunar: kalıtım ("is-a" ilişkisi) ve kompozisyon ("has-a" ilişkisi).
İşte kalıtımın bir "is-a" ilişkisi oluşturmasına dair bir örnek:
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
return f"{self.name} is eating"
class Dog(Animal): # Dog bir "Animal"dır
def bark(self):
return "Woof!"
dog = Dog("Buddy")
print(dog.eat()) # Kalıtımla alınan metot
print(dog.bark()) # Kendi metoduİşte bir "has-a" (sahip olma) ilişkisi oluşturan kompozisyon örneği:
class Engine:
def start(self):
return "Engine started"
def stop(self):
return "Engine stopped"
class Car: # Araba bir motora "sahiptir"
def __init__(self):
self.engine = Engine() # Kompozisyon
def start(self):
return self.engine.start()
car = Car()
print(car.start()) # Bileşen olarak eklenen motoru kullanırHer iki yaklaşımı daha karmaşık bir örnekle karşılaştırın:
# Kalıtım yaklaşımı
class Bird:
def move(self):
return "Flying"
class Duck(Bird):
def quack(self):
return "Quack!"
# Kompozisyon yaklaşımı
class FlyBehavior:
def move(self):
return "Flying"
class SwimBehavior:
def move(self):
return "Swimming"
class VersatileDuck:
def __init__(self):
self.fly_behavior = FlyBehavior()
self.swim_behavior = SwimBehavior()
def fly(self):
return self.fly_behavior.move()
def swim(self):
return self.swim_behavior.move()
def quack(self):
return "Quack!"Her iki yaklaşımı da test edin:
# Kalıtım
duck1 = Duck()
print(duck1.move()) # Uçuyor
print(duck1.quack()) # Vak vak!
# Kompozisyon
duck2 = VersatileDuck()
print(duck2.fly()) # Uçuyor
print(duck2.swim()) # Yüzüyor
print(duck2.quack()) # Vak vak!Çıktı:
Buddy is eating
Woof!
Engine started
Flying
Quack!
Flying
Swimming
Quack!Temel farklar:
Kalıtım (Inheritance):
- Ebeveyn ve çocuk arasında sıkı bağlılık (Tight coupling)
- "Is-a" ilişkisi
- Ebeveyndeki değişiklikler tüm çocukları etkiler
- Gerçek hiyerarşik ilişkiler için en iyisidir
Kompozisyon:
- Nesneler arasında gevşek bağlılık
- "Has-a" ilişkisi
- Daha esnek - çalışma zamanında davranışı değiştirebilir
- Test etmesi ve modifiye etmesi daha kolay
Anahtar Nokta: Gerçek bir "is-a" ilişkisine sahip olduğunuzda kalıtımı (inheritance) kullanın. Esneklik ve gevşek bağlılığa (loose coupling) ihtiyaç duyduğunuzda kompozisyonu (composition) kullanın. "Kalıtım yerine kompozisyon" (composition over inheritance) ilkesi, esnekliği ve sürdürülebilirliği nedeniyle çoğu durumda kompozisyonun tercih edilmesini önerir.
Görev
OrtaBu meydan okumada, hem kalıtım (inheritance) hem de bileşim (composition) desenlerini kullanarak bir medya kütüphanesi sistemi uygulayacaksınız.
Her birinin içindeki TODO yorumlarını takip ederek aşağıdaki dosyaları düzenlemeniz gerekmektedir:
media.py,book.py,movie.py,musicalbum.py- Kalıtım uygulaması içinmediaitem.py,bookcomposition.py,moviecomposition.py,musicalbumcomposition.py- Bileşim uygulaması için
Her medya türü şunlara sahip olmalıdır:
- Başlık (Title), oluşturucu (creator - yazar/yönetmen/sanatçı) ve yıl (year) öznitelikleri
- Uygun
display_info()metodu
Kopya kağıdı
Nesne yönelimli programlama, kodun yeniden kullanımı için iki ana yaklaşım sunar: kalıtım ("is-a" ilişkisi) ve bileşim ("has-a" ilişkisi).
Kalıtım örneği:
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
return f"{self.name} is eating"
class Dog(Animal): # Dog "is an" Animal (Köpek bir Hayvandır)
def bark(self):
return "Woof!"
dog = Dog("Buddy")
print(dog.eat()) # Kalıtım alınan metot
print(dog.bark()) # Kendi metoduBileşim örneği:
class Engine:
def start(self):
return "Engine started"
class Car: # Car "has an" Engine (Araba bir Motora sahiptir)
def __init__(self):
self.engine = Engine() # Bileşim
def start(self):
return self.engine.start()
car = Car()
print(car.start()) # Bileştirilmiş motoru kullanırTemel farklar:
Kalıtım:
- Ebeveyn ve çocuk arasında sıkı bağlılık
- "Is-a" ilişkisi
- Ebeveyndeki değişiklikler tüm çocukları etkiler
- Gerçek hiyerarşik ilişkiler için en iyisidir
Bileşim:
- Nesneler arasında gevşek bağlılık
- "Has-a" ilişkisi
- Daha esnektir - çalışma zamanında davranış değiştirebilir
- Test edilmesi ve değiştirilmesi daha kolaydır
Gerçek "is-a" ilişkileri için kalıtımı kullanın. Esneklik ve gevşek bağlılık için bileşimi kullanın. "Kalıtım yerine bileşim" ilkesi, çoğu durumda bileşimin tercih edilmesini önerir.
Kendin dene
from media import Media
from book import Book
from movie import Movie
from musicalbum import MusicAlbum
from mediaitem import MediaItem
from bookcomposition import BookComposition
from moviecomposition import MovieComposition
from musicalbumcomposition import MusicAlbumComposition
# Kapsamlı test durumu işleyicisi
test_case = input()
def test_inheritance_basic():
book = Book("The Hobbit", "J.R.R. Tolkien", 1937)
movie = Movie("The Matrix", "Wachowski Sisters", 1999)
album = MusicAlbum("Abbey Road", "The Beatles", 1969)
assert book.display_info() == "Book: The Hobbit by J.R.R. Tolkien (1937)"
assert movie.display_info() == "Movie: The Matrix directed by Wachowski Sisters (1999)"
assert album.display_info() == "Music Album: Abbey Road by The Beatles (1969)"
def test_composition_basic():
book_comp = BookComposition("Dune", "Frank Herbert", 1965)
movie_comp = MovieComposition("Inception", "Christopher Nolan", 2010)
album_comp = MusicAlbumComposition("Thriller", "Michael Jackson", 1982)
assert book_comp.display_info() == "Book: Dune by Frank Herbert (1965)"
assert movie_comp.display_info() == "Movie: Inception directed by Christopher Nolan (2010)"
assert album_comp.display_info() == "Music Album: Thriller by Michael Jackson (1982)"
def test_inheritance_relationships():
book = Book("Test Book", "Test Author", 2000)
movie = Movie("Test Movie", "Test Director", 2001)
album = MusicAlbum("Test Album", "Test Artist", 2002)
assert isinstance(book, Book)
assert isinstance(book, Media)
assert isinstance(movie, Movie)
assert isinstance(movie, Media)
assert isinstance(album, MusicAlbum)
assert isinstance(album, Media)
def test_attribute_access():
# Kalıtım yaklaşımını test et
book = Book("Test Book", "Test Author", 2000)
assert book.title == "Test Book"
assert book.creator == "Test Author"
assert book.year == 2000
# Kompozisyon yaklaşımını test et
book_comp = BookComposition("Test Book", "Test Author", 2000)
assert book_comp.media.title == "Test Book"
assert book_comp.media.creator == "Test Author"
assert book_comp.media.year == 2000
def test_polymorphism():
media_list = [
Book("Book1", "Author1", 2001),
Movie("Movie1", "Director1", 2002),
MusicAlbum("Album1", "Artist1", 2003)
]
assert media_list[0].display_info() == "Book: Book1 by Author1 (2001)"
assert media_list[1].display_info() == "Movie: Movie1 directed by Director1 (2002)"
assert media_list[2].display_info() == "Music Album: Album1 by Artist1 (2003)"
def test_edge_cases():
# Boş dizeler
book = Book("", "", 0)
assert book.display_info() == "Book: by (0)"
# Özel karakterler - buradaki sözdizimi hatası düzeltildi
movie = Movie("Test\"Movie", "Test\\nDirector", -1)
assert movie.display_info() == "Movie: Test\"Movie directed by Test\\nDirector (-1)"
# Uç yıllar
album = MusicAlbum("Test Album", "Test Artist", 9999)
assert album.display_info() == "Music Album: Test Album by Test Artist (9999)"
def test_stress():
# Çok sayıda medya nesnesi oluştur
books = [Book(f"Book{i}", f"Author{i}", 2000+i) for i in range(100)]
movies = [Movie(f"Movie{i}", f"Director{i}", 2000+i) for i in range(100)]
albums = [MusicAlbum(f"Album{i}", f"Artist{i}", 2000+i) for i in range(100)]
for i, book in enumerate(books):
assert book.display_info() == f"Book: Book{i} by Author{i} ({2000+i})"
for i, movie in enumerate(movies):
assert movie.display_info() == f"Movie: Movie{i} directed by Director{i} ({2000+i})"
for i, album in enumerate(albums):
assert album.display_info() == f"Music Album: Album{i} by Artist{i} ({2000+i})"
# Girişe göre uygun testi çalıştır
if test_case == "default_test" or test_case == "":
test_inheritance_basic()
test_composition_basic()
print("All tests passed!")
elif test_case == "inheritance_test":
test_inheritance_basic()
test_inheritance_relationships()
print("Inheritance tests passed!")
elif test_case == "composition_test":
test_composition_basic()
print("Composition tests passed!")
elif test_case == "polymorphism_test":
test_polymorphism()
print("Polymorphism tests passed!")
elif test_case == "attribute_test":
test_attribute_access()
print("Attribute tests passed!")
elif test_case == "edge_cases":
test_edge_cases()
print("Edge case tests passed!")
elif test_case == "stress_test":
test_stress()
print("Stress tests passed!")Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Object Oriented Programming bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesnelerself ParametresiMetotlarÖzniteliklerYapıcı Metot (__init__)Özet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtımsuper() FonksiyonuMetot Geçersiz KılmaÇoklu KalıtımMetot Çözümleme SırasıÖzet - Çalışan Hiyerarşisi7Özel Metotlar
Sihirli Metotlara GirişOperatör Aşırı YüklemeKapsayıcı Sihirli MetotlarıÖzet - Özel Liste10Tasarım Kalıpları Bölüm 1
Tasarım kalıplarına girişSingleton KalıbıFactory KalıbıObserver KalıbıStrategy Kalıbı13Final Meydan Okumaları
E-öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi5Çok Biçimlilik (Polymorphism)
Metot Geçersiz Kılmaya Yeniden BakışDuck TypingSoyut Sınıflar ve MetotlarArayüz TasarımıÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kompozisyon ve KalıtımMixinsStatik ve Sınıf MetotlarıSınıf DekoratörleriBağlam Yöneticileri11Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit Kalıbı