JavaScript Advanced Concepts

JavaScript’te Çoklu Kalıtımın Ustası Olmak: Bileşim ve Temsil

Spread the love

JavaScript, Python veya Java gibi dillerdeki gibi çoklu kalıtımı aynı şekilde desteklemez. Bu tasarım seçimi, kalıtım belirsizliğinin ortaya çıktığı “elmas problemi” gibi karmaşıklıkları önler. Bununla birlikte, kompozisyon ve davranışsal delege etme gibi akıllı teknikler aracılığıyla benzer işlevselliğe ulaşmak mümkündür. Bu makale, bu yaklaşımları, güçlü ve zayıf yönlerini vurgulayarak ele almaktadır.

İçindekiler Tablosu

Kompozisyon: İşlevselliği Birleştirme

Kompozisyon, onlardan kalıtım almadan mevcut sınıfların işlevselliğini kullanan yeni bir sınıf oluşturmayı içerir. Bu, daha iyi kapsüllemeyi teşvik eder ve çoklu kalıtımın tuzaklarından kaçınır. Bunu, istenen sınıfların örneklerini oluşturarak ve yöntemlerini yeni sınıfımıza dahil ederek başarırız.

Pratik bir örnek ile açıklayalım. Diyelim ki bir Car sınıfımız ve bir Engine sınıfımız var:


class Car {
  constructor(model) {
    this.model = model;
  }
  drive() {
    console.log(`${this.model} gidiyor.`);
  }
}

class Engine {
  start() {
    console.log("Motor çalıştı.");
  }
  stop() {
    console.log("Motor durdu.");
  }
}

Şimdi, hem Car hem de Engine‘ı içeren bir SportsCar sınıfı oluşturalım:


class SportsCar {
  constructor(model) {
    this.car = new Car(model);
    this.engine = new Engine();
  }
  drive() {
    this.engine.start();
    this.car.drive();
  }
  stop() {
    this.engine.stop();
  }
}

let mySportsCar = new SportsCar("Porsche 911");
mySportsCar.drive(); // Çıktı: Motor çalıştı. Porsche 911 gidiyor.
mySportsCar.stop();  // Çıktı: Motor durdu.

Bu örnekte, SportsCar, Car veya Engine‘dan kalıtım almıyor, ancak işlevselliklerini etkili bir şekilde birleştiriyor. Bu yaklaşım basit ve anlaşılması kolaydır.

Davranışsal Delege Etme: Dinamik Metot Gönderimi

Davranışsal delege etme daha esnek bir yaklaşım sunar. Yeni bir sınıf, metot çağrılarını diğer sınıfların örneklerine devrederek, bağlama bağlı olarak dinamik davranış değişikliklerine olanak tanır. Bu, sınıflar arasındaki ilişki statik olmadığında özellikle kullanışlıdır.

Car ve Engine örneğine geri dönelim. Bir DelegatingCar sınıfı oluşturacağız:


class DelegatingCar {
  constructor(delegates = []) {
    this.delegates = delegates;
  }
  addDelegate(delegate) {
    this.delegates.push(delegate);
  }
  performAction(action, ...args) {
    for (const delegate of this.delegates) {
      if (typeof delegate[action] === 'function') {
        return delegate[action](...args);
      }
    }
    throw new Error(`'${action}' eylemi bulunamadı.`);
  }
}

let myDelegatingCar = new DelegatingCar([new Car("Ferrari"), new Engine()]);
myDelegatingCar.performAction('drive'); //Çıktı: Ferrari gidiyor.
myDelegatingCar.performAction('start'); //Çıktı: Motor çalıştı.

DelegatingCar, istekleri uygun delegeye yönlendirmek için merkezi bir performAction metodu kullanır. Bu, daha dinamik kontrol sağlar, ancak basit kompozisyona göre karmaşıklık ekler.

Doğru Yaklaşımı Seçme

Hem kompozisyon hem de davranışsal delege etme, JavaScript’te çoklu kalıtıma güçlü alternatifler sunar. Kompozisyon genellikle daha basit ve daha okunabilirdir, bu da onu çoğu senaryo için uygun hale getirir. Davranışsal delege etme, dinamik davranış için daha fazla esneklik sunar, ancak ek karmaşıklık getirir. En uygun seçim, uygulamanızın özel gereksinimlerine bağlıdır. Netliği ve sürdürülebilirliği önceliklendirmek çok önemlidir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir