Menu
Coddy logo textTech

Kompozisyon vs Kalıtım

Coddy'nin Java Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 47 / 87.

Kalıtım bir "is-a" (bir ...-dır) ilişkisi oluşturur: bir Dog bir Animal'dır. Peki ya bir sınıf, kendisi olmadığı bir şeyden işlevselliğe ihtiyaç duyarsa? İşte burada, bunun yerine bir "has-a" (bir ...-ya sahiptir) ilişkisi kuran kompozisyon (composition) devreye girer.

Kompozisyon ile bir sınıf, diğer sınıfları genişletmek yerine onların örneklerini alan (field) olarak içerir:

// Kalıtım yaklaşımı: Araba bir Motordur (mantıklı değil)
class Car extends Engine { }

// Kompozisyon yaklaşımı: Arabanın bir Motoru VARDIR (mantıklı)
class Car {
    private Engine engine;
    
    public Car(Engine engine) {
        this.engine = engine;
    }
    
    public void start() {
        engine.ignite();
    }
}

Kompozisyon çeşitli avantajlar sunar. Motorları değiştirmek gibi, çalışma zamanında oluşturulan nesneyi değiştirebilirsiniz.

Ayrıca, Java'da kalıtımın izin vermediği bir özellik olan birden fazla sınıftan gelen davranışları birleştirebilirsiniz. Bileşik sınıf, yalnızca kendi seçtiği metotları dışarıya açarak daha iyi bir kapsülleme sağlar.

Pratik bir kural: Gerçek bir "is-a" ilişkisi olduğunda ve alt sınıf (subclass), üst sınıfın (parent) gerçekten özelleşmiş bir versiyonunu temsil ettiğinde kalıtım kullanın.

Başka bir sınıfın işlevselliğini, o türden olmadan kullanmanız gerektiğinde kompozisyonu (composition) kullanın. Pek çok deneyimli geliştirici şu ilkeyi takip eder: "kalıtım yerine kompozisyonu tercih et" çünkü bu, daha esnek ve bakımı kolay kodlar yazılmasını sağlar.

challenge icon

Görev

Kolay

"Has-a" (sahip olma) ilişkisini göstermek için kompozisyon kullanarak bir bilgisayar sistemi oluşturalım. Bir Computer sınıfının bileşenlerinden miras alması yerine (ki bu mantıklı olmazdı), bilgisayarınız çalışması için gereken parçaları içerecektir.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • Processor.java: Bir CPU'yu temsil eden bir sınıf oluşturun. Bir Processor iki özel (private) alana sahiptir: brand (String) ve speedGHz (double). Her iki alanı da başlatan bir yapıcı (constructor) ve her biri için getter metotları ekleyin. Şu String değerini döndüren bir process() metodu ekleyin: [brand] processing at [speedGHz] GHz
  • Memory.java: RAM'i temsil eden bir sınıf oluşturun. Bir Memory iki özel alana sahiptir: type (String, "DDR4" veya "DDR5" gibi) ve sizeGB (int). Bir yapıcı, getter metotları ve şu değeri döndüren bir load() metodu ekleyin: Loading [sizeGB]GB [type] memory
  • Computer.java: İşte kompozisyonun parladığı yer burası! Computer sınıfınız, özel alanlar olarak bir Processor ve bir Memory'ye sahip olmalıdır—onları genişletmez (extend), onları içerir. Her iki bileşeni de kabul eden bir yapıcı ekleyin. Bileşenlerini kullanarak bilgisayarın başladığını gösteren çok satırlı bir String döndüren bir boot() metodu ekleyin:
    Booting computer...
    [processor.process() result]
    [memory.load() result]
    System ready!
    Ayrıca şu değeri döndüren bir getSpecs() metodu ekleyin: Specs: [processor brand] CPU, [memory sizeGB]GB [memory type]
  • Main.java: Oluşturduğunuz sistemi hayata geçirin! Dört girdi alacaksınız: işlemci markası (String), işlemci hızı (double), bellek türü (String) ve bellek boyutu (int).

    Bu değerlerle bir Processor ve Memory oluşturun, ardından bunları bir Computer içinde birleştirin. boot() metodunu çağırmanın sonucunu yazdırın, ardından getSpecs() sonucunu yazdırın.

Sırasıyla dört girdi alacaksınız: işlemci markası, işlemci hızı (GHz), bellek türü ve bellek boyutu (GB).

Computer sınıfının, bileşenlerin kendisi olmaya çalışmak yerine işi onlara nasıl devrettiğine (delegate) dikkat edin—kompozisyonun gücü budur! Computer, ona verdiğiniz herhangi bir Processor veya Memory'yi kullanabilir, bu da tasarımı esnek ve gerçekçi kılar.

Kopya kağıdı

Kompozisyon (Composition), bir sınıfın diğer sınıfları genişletmek yerine onları alan (field) olarak içerdiği bir "has-a" (sahip olma) ilişkisi oluşturur.

Kalıtım (Inheritance) vs Kompozisyon (Composition):

// Kalıtım: Araba bir Motordur (mantıklı değil)
class Car extends Engine { }

// Kompozisyon: Arabanın bir Motoru VARDIR (mantıklı)
class Car {
    private Engine engine;
    
    public Car(Engine engine) {
        this.engine = engine;
    }
    
    public void start() {
        engine.ignite();
    }
}

Kompozisyonun Avantajları:

  • Nesneler çalışma zamanında (runtime) değiştirilebilir
  • Birden fazla sınıftan gelen davranışlar birleştirilebilir
  • Daha iyi kapsülleme (encapsulation) - sadece seçilen metotlar dışarı açılır
  • Daha esnek ve bakımı kolay kod

Ne Zaman Kullanılmalı:

  • Kalıtım: Gerçek bir "is-a" (bir ...-dır) ilişkisi olduğunda ve alt sınıf, üst sınıfın özelleşmiş bir versiyonu olduğunda kullanın
  • Kompozisyon: O türden olmadan başka bir sınıfın işlevselliğine ihtiyaç duyduğunuzda kullanın

En İyi Uygulama: "Kalıtım yerine kompozisyonu tercih edin"

Kendin dene

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Girdileri oku
        String processorBrand = scanner.nextLine();
        double processorSpeed = Double.parseDouble(scanner.nextLine());
        String memoryType = scanner.nextLine();
        int memorySize = Integer.parseInt(scanner.nextLine());
        
        // TODO: Marka ve hız ile bir Processor oluşturun
        
        // TODO: Tip ve boyut ile bir Memory oluşturun
        
        // TODO: Processor ve Memory bileşenlerini birleştirerek bir Computer oluşturun
        
        // TODO: boot() sonucunu yazdırın
        
        // TODO: getSpecs() sonucunu yazdırın
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler