Menu
Coddy logo textTech

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ır

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

challenge icon

Görev

Orta

Bu 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çin
  • mediaitem.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 metodu

Bileş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ır

Temel 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!")
quiz iconKendini test et

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