Kural
Tercih kompozisyon kullan kalıtım
Derin kalıtım hiyerarşiler oluştur sıkı bağlantı
ve sistemleri kod zorlaştırmak anlaşılması anlaşılması ve bakımı
Desteklenen diller: 45+Giriş
Kalıtım, üst sınıf ile alt sınıf arasında sıkı bir bağ oluşturur; bu da kodu kırılgan hale getirir ve değiştirilmesini zorlaştırır. Bir sınıf davranışını miras aldığında, üst sınıfının uygulama ayrıntılarına bağımlı hale gelir. Yöntemleri geçersiz kılan ancak yine de süper özellikle sorunlu olup, kendi mantıklarını miras alınan davranışlarla öyle bir şekilde harmanlarlar ki, ebeveyn nesne değiştiğinde bu yapı bozulur. Bileşim, nesnelerin diğer nesnelere görev devretmesine olanak tanıyarak bu sorunu çözer; böylece gevşek bağlanma ve görevlerin net bir şekilde ayrılması sağlanır.
Neden önemli?
Karışık endişeler ve sıkı bağlantı: Kalıtım, birbiriyle ilgisi olmayan unsurları aynı sınıf hiyerarşisine dahil eder. Bir ödeme işlemcisinden miras alan bir tekrarlayan ödeme sınıfı, zamanlama mantığını ödeme işlemeyle karıştırır. Şunu çağırmanız gerektiğinde super.process() ve ardından kendi davranışınızı eklediğinizde, üst sınıfın uygulamasıyla sıkı bir şekilde bağlanmış olursunuz. Eğer üst sınıfın process() Yöntemlerde değişiklik yapıldığında, alt sınıf beklenmedik şekillerde hataya düşer.
İstenmeyen davranışların devralınması: Alt sınıflar, ihtiyaç duymadıkları veya farklı uygulamalar gerektiren yöntemler de dahil olmak üzere, üst sınıflarından her şeyi devralır. Tekrarlayan bir ödeme, şunları devralır: refund() Bu mantık tek seferlik ödemeler için tasarlanmıştır, ancak abonelik iadeleri farklı şekilde işler. Ya yöntemleri geçersiz kılar ve kafa karışıklığına yol açarsınız, ya da uygun olmayan miras alınan davranışla yetinirsiniz.
Hassas temel sınıf sorunu: Ana sınıflarda yapılan değişiklikler tüm alt sınıflara yansır. Şu şekilde değiştirme Kredi Kartı Ödemesi ödemelerin işlenmesi, şunları etkiler: Tekrarlayan Kredi Kartı Ödemesi Değişiklik, zamanlama ile ilgisiz olsa bile. Bu durum, yeniden yapılandırmayı riskli hale getirir; çünkü hangi alt sınıfların çalışmaz hale geleceğini öngöremezsiniz.
Test karmaşıklığı: Kalıtım hiyerarşisinin derinliklerinde yer alan sınıfları test etmek, üst sınıfın davranışını anlamayı gerektirir. Tekrarlayan ödeme planlamasını test etmek için, kredi kartı işleme mantığı, Stripe API çağrıları ve doğrulama işlemleriyle de ilgilenmeniz gerekir. Bileşim yaklaşımı, basit bir sahte ödeme nesnesi kullanarak planlamayı test etmenize olanak tanır.
Kod örnekleri
❌ Uygun değil:
class Payment {
constructor(amount, currency) {
this.amount = amount;
this.currency = currency;
}
async process() {
throw new Error('Must implement in subclass');
}
async refund() {
throw new Error('Must implement in subclass');
}
async sendReceipt(email) {
// All paymet types need receipts
await emailService.send(email, this.buildReceipt());
}
}
class CreditCardPayment extends Payment {
constructor(amount, currency, cardToken, billingAddress) {
super(amount, currency);
this.cardToken = cardToken;
this.billingAddress = billingAddress;
}
async process() {
await this.validateCard();
return await stripe.charges.create({
amount: this.amount * 100,
source: this.cardToken,
currency: this.currency
});
}
async refund() {
await this.validateRefund();
return await stripe.refunds.create({ charge: this.chargeId });
}
async validateCard() {
// Card validation logic
}
}
// Problem: RecurringCreditCardPayment's main concern is dealing with scheduling
// and not the actual payment
class RecurringCreditCardPayment extends CreditCardPayment {
constructor(amount, currency, cardToken, billingAddress, schedule) {
super(amount, currency, cardToken, billingAddress);
this.schedule = schedule;
}
async process() {
// Problem: Need to override parent's process() but also use it
await super.process();
await this.scheduleNextPayment();
}
async scheduleNextPayment() {
// Subscription scheduling
}
// Problem: Inherits refund() from parent but refunding
// subscriptions needs different logic
}Neden yanlış: Tekrarlayan Kredi Kartı Ödemesi Ödeme işleme mantığını devralır, ancak asıl odak noktası ödemeler değil, zamanlamadır. Şunu çağırmalıdır: super.process() ve bunu zamanlama davranışıyla sararak sıkı bir bağ oluşturur. Sınıf, refund() ana hesap üzerinden yapılır, ancak aboneliklerin iadesi tek seferlik ödemelerden farklı bir mantık gerektirir. Şu değişiklikler: Kredi Kartı Ödemesi etkilemek Tekrarlayan Kredi Kartı Ödemesi bu değişiklikler zamanlamayla ilgisiz olsa bile.
✅ Uygunluk:
class CreditCardPayment extends Payment {
constructor(amount, currency, cardToken, billingAddress) {
super(amount, currency);
this.cardToken = cardToken;
this.billingAddress = billingAddress;
}
async process() {
await this.validateCard();
return await stripe.charges.create({
amount: this.amount * 100,
source: this.cardToken,
currency: this.currency
});
}
async refund() {
await this.validateRefund();
return await stripe.refunds.create({ charge: this.chargeId });
}
async validateCard() {
// Card validation logic
}
}
class RecurringCreditCardPayment {
constructor(creditCardPayment, schedule) {
this.creditCardPayment = creditCardPayment;
this.schedule = schedule;
}
async scheduleNextPayment() {
this.schedule.onNextCyle(() => {
await this.creditCardPayment.process();
})
}
}
const recurringCreditCardPayment = new RecurringCreditCardPayment(
new CreditCardPayment(),
new Schedule(),
);Bunun önemi: Tekrarlayan Kredi Kartı Ödemesi yalnızca planlamaya odaklanır ve ödeme işlemlerini oluşturulan birime devreder Kredi Kartı Ödemesi örneği. Kalıtım olmaması, üst sınıfın uygulamasına sıkı bir bağlanma olmadığı anlamına gelir. Kredi kartı işlemlerinde yapılan değişiklikler, zamanlama mantığını etkilemez. Zamanlama kodunda herhangi bir değişiklik yapılmasına gerek kalmadan, ödeme örneği herhangi bir ödeme yöntemiyle değiştirilebilir.
Sonuç
Kalıtım yoluyla konuları birbirine karıştırmak yerine, kompozisyonu kullanarak bunları birbirinden ayırın. Bir sınıfın başka bir sınıfın işlevselliğine ihtiyacı olduğunda, onu bir bağımlılık olarak kabul edin ve o sınıftan miras almak yerine işlevleri ona devredin. Bu, gevşek bağlanma sağlar, test etmeyi kolaylaştırır ve bir sınıftaki değişikliklerin başka bir sınıfı bozmasını önler.

