Menu
Coddy logo textTech

Kompozisyon ve Kalıtım

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

Kalıtımın bir "is-a" (bir ...-dır) ilişkisi oluşturduğunu öğrendiniz - bir Dog bir Animal'dır. Ancak başka bir güçlü yaklaşım daha var: "has-a" (sahiptir) ilişkisi oluşturan kompozisyon (composition). Davranışı miras almak yerine, bir sınıf diğer sınıfların örneklerini içerir ve işi onlara devreder.

Bir Car sınıfını ele alalım. Kalıtım ile, bir Engine sınıfını genişletmeyi deneyebilirsiniz - ancak bir araba bir motor değildir, bir motora sahiptir:

class Engine {
  void start() => print('Engine started');
}

class Car {
  final Engine _engine = Engine();  // Kompozisyon: Araba bir Motora SAHİPTİR
  
  void start() {
    _engine.start();  // Görevi motora devret
    print('Car is ready to drive');
  }
}

void main() {
  var car = Car();
  car.start();
}

Kompozisyonun temel avantajı esnekliktir. Kalıtım ile tek bir üst sınıfa kilitlenirsiniz. Kompozisyon ile birden fazla bileşeni birleştirebilir ve hatta bunları çalışma zamanında değiştirebilirsiniz:

class ElectricEngine {
  void start() => print('Electric motor humming');
}

class HybridCar {
  Engine? _gasEngine;
  ElectricEngine? _electricEngine;
  
  HybridCar({bool useElectric = false}) {
    if (useElectric) {
      _electricEngine = ElectricEngine();
    } else {
      _gasEngine = Engine();
    }
  }
}

Yaygın bir ilke "kalıtım yerine kompozisyonu tercih et" şeklindedir. Gerçek bir "is-a" ilişkisi olduğunda ve polimorfizme ihtiyaç duyduğunuzda kalıtımı kullanın. Sıkı bağlılık (tight coupling) olmadan davranışı yeniden kullanmak istediğinizde veya bir nesnenin birden fazla kaynaktan yeteneklere ihtiyacı olduğunda kompozisyonu kullanın.

challenge icon

Görev

Kolay

Kompozisyon (composition) kullanarak bir bilgisayar sistemi inşa edelim! Bir bilgisayarı parçalarından miras alacak şekilde tasarlamak yerine, ayrı bileşen sınıfları oluşturacak ve bunları bir araya getireceksiniz - çünkü bir bilgisayarın bir CPU'su vardır ve belleği vardır, kendisi bir CPU veya bellek değildir.

Kodunuzu üç dosyada organize edeceksiniz:

  • components.dart: Bilgisayar parçalarını temsil eden iki bileşen sınıfı oluşturun:
    • String brand ve double speedGHz alanlarına sahip bir CPU sınıfı. Şu dizeyi döndüren bir process() metodu ekleyin: '$brand processing at ${speedGHz}GHz'
    • int sizeGB alanına sahip bir Memory sınıfı. Şu dizeyi döndüren bir load() metodu ekleyin: 'Loading ${sizeGB}GB of data'
  • computer.dart: Bileşenleri birleştirmek için kompozisyon kullanan bir Computer sınıfı oluşturun. Bilgisayarınız şunları yapmalıdır:
    • Bir String name alanına sahip olmalı
    • Bir CPU ve bir Memory örneği içermeli (kompozisyon - bilgisayar bu parçalara SAHİPTİR)
    • Her iki bileşeni de dahili olarak oluşturmak için gerekli tüm değerleri yapıcı metodu (constructor) aracılığıyla kabul etmeli
    • Her iki bileşene görev devreden ve üç satır yazdıran bir boot() metoduna sahip olmalı: bilgisayarın adı ve ardından ' starting...', sonra CPU'nun process metodunun sonucu, ardından Memory'nin load metodunun sonucu
    • Sistemi tanımlayan bir dize döndüren specs() metoduna sahip olmalı: '$name: ${cpu.brand} ${cpu.speedGHz}GHz, ${memory.sizeGB}GB RAM'
  • main.dart: Dosyalarınızı içe aktarın ve kompozisyonun işleyişini gösterin:
    • 3.5 GHz hızında çalışan bir 'Intel' CPU'ya ve 16 GB belleğe sahip, 'Workstation' adında bir Computer oluşturun
    • boot() metodunu çağırın
    • specs() metodunun sonucunu yazdırın

Computer sınıfının CPU veya Memory sınıflarını genişletmediğine (extend), aksine onları içerdiğine ve işi onlara devrettiğine dikkat edin. Bu, kompozisyonun oluşturduğu "has-a" (sahip olma) ilişkisidir!

Beklenen çıktı:

Workstation starting...
Intel processing at 3.5GHz
Loading 16GB of data
Workstation: Intel 3.5GHz, 16GB RAM

Kopya kağıdı

Kompozisyon (Composition), bir sınıfın diğer sınıflardan miras almak yerine, diğer sınıfların örneklerini içerdiği ve işi onlara devrettiği bir "has-a" (sahip olma) ilişkisi oluşturur.

Temel kompozisyon örneği:

class Engine {
  void start() => print('Engine started');
}

class Car {
  final Engine _engine = Engine();  // Car HAS an Engine
  
  void start() {
    _engine.start();  // Delegate to the engine
    print('Car is ready to drive');
  }
}

Esneklik sağlayan kompozisyon - bileşenleri değiştirme:

class ElectricEngine {
  void start() => print('Electric motor humming');
}

class HybridCar {
  Engine? _gasEngine;
  ElectricEngine? _electricEngine;
  
  HybridCar({bool useElectric = false}) {
    if (useElectric) {
      _electricEngine = ElectricEngine();
    } else {
      _gasEngine = Engine();
    }
  }
}

Kompozisyon ve kalıtım ne zaman kullanılır:

  • Polimorfizme ihtiyaç duyduğunuz gerçek "is-a" (bir ...-dır) ilişkileri için kalıtımı (inheritance) kullanın
  • Davranışı sıkı bağlılık (tight coupling) olmadan yeniden kullanmak için veya bir nesnenin birden fazla kaynaktan yeteneklere ihtiyacı olduğunda kompozisyonu (composition) kullanın
  • Genel kural: "kalıtım yerine kompozisyonu tercih edin"

Kendin dene

import 'computer.dart';

void main() {
  // TODO: Şunlara sahip "Workstation" adında bir Computer oluşturun:
  // - 3.5 GHz hızında çalışan Intel CPU
  // - 16 GB bellek

  // TODO: boot() metodunu çağırın

  // TODO: specs() 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