Композиція vs Наслідування

Недавно доводилось працювати з людьми які на дух не переносять наслідування. Всюди де можна і не можна використовували композицію.

Щоб зберегти тверезість розуму вирішив спробувати перелічити коли і що треба використовувати.

Наслідування

1) коли є is-a залежність

2) коли is-a є постійною в часі, тобто стан об'єкту моделюється не класами, а властивостями класу

Композиція

1) коли можливо has-a pалежність

2) коли потрібно перевикористати код

3) коли необхідно поліморфізм, але немає is-a зв'язку — краще використати інтерфейси

4) коли супер клас є недоступним до модифікації (чи може краще зразу адаптер?)

Щодо базових класів — то їх краще зразу оголошувати як abstract щоб потім не було мороки, коли коду багато.

Якісь ще є думки на цю тему?

Коментарі 10

mamantoha - 23 липня 2009, 01:17

На цю тему думок нема. Вперше чую про таке поняття як композиція.

Але я довго думав про те, що буде краще: зразу чи відразу (чи одразу), але не знаю.

zenyk - 23 липня 2009, 11:18

наслідування (inheritance) це:

class A {}
class B extends A {}

композиція (composition) це:

class A {}
class B {
  private A a;
}
cyba - 23 липня 2009, 12:28

Особисто я, зовсім не фахівець у «канонічному» ООП, завжди був впевнений у тому, що це називається агрегацією.

zenyk - 23 липня 2009, 14:01

багато коду треба щоб показати різницю між агрегацією та композицією :)

агрегація та композиція це підтипи асоціації.

різниця між композицією та асоціацією полягає у тому, що об'єкти у першому є частиною класу і також мають такий самий життєвий цикл. тобто коли знищується клас, при композиції, також знищуються його елементи. в той час при агрегації, об'єкти можуть існувати незалежно один від одного.

приклад композиції: будинок та квартири (щось типу owns)

приклад агрегації: будинок та мешканці

в першому випадку квартири не можуть існувати без будинку, в другому випадку мешканці можуть існувати без будинку.

але і перше і друге це асоціація

cyba - 23 липня 2009, 14:14

Цікаво. ))) Ок, ну а нащо тоді відмовлятися від is-a (як було сказано вище), якщо будинки бувають зовсім різними? Якщо вже брати на озброєння моделювання навколишнього світу, для чого і була розроблена концепція ООП, то як можна відмовитися від is-a, тим паче тоді, якщо саме цей зв'язок позиціонується в догмах ООП ледь не як основний? Мені здається «rectangle is a shape» природне і обгрунтоване аксіоматично чи що, на відміну від «rectangle has a shape», яке більше подібне на нісенітницю (я тут не враховую української мови, яка дозволяє сказати «має форму»). Просто де присутній очевидний is-a, нехай він там і залищається; де присутній явний has-a — нехай там і використовується, а не замінює собою все можливе. Таке собі трішки weird.

zenyk - 23 липня 2009, 15:30

тому що є чистий is-a, а є коли is-a показує стан.

коли is-a показує стан, наприклад людина може бути у стані: підліток, дорослий та похилогоВіку, тоді краще це робити не класами:

class Людина {}
class Підліток extends Людина {}
class Дія {
  Людина людина = new Підліток();
}
class Людина {}
class Дія {
  Людина людина = new Людина(СтаниЛюдей.Підліток);
}

:)

cyba - 23 липня 2009, 16:35

Можливо, я не розумію, але is-a, що показує стан, це не добре. Щоби змоделювати стан, я би застосовував лише has-a.

zenyk - 27 липня 2009, 11:38

а це і є has-a :)

тобто можна сказати що Підліток це стан Людини. Хоча в певний момент Підліток is-a Людина, в часі це не завжди так. тому з точки зору реалізації (а не дизайну) доцільніше це показати як стан класу, а не як окремий клас.

savostin - 23 липня 2009, 12:51
class A {}
class B {
  private A a;
}

а точто private? классы будут несколько не равнозначные.

zenyk - 23 липня 2009, 14:04

так, але у цьому і сила, так як можна незалежно від A міняти контракт B

це дуже узагальнено, в принципі може бути і не private i.e. public, але тоді це точно не композиція так як можна отримати посилання на A, яке буде жити після смерті екземпляра B.

Коментувати
© 2009 - 2020, Розробка - соціальна ІТ спільнота.
Контакти: info@rozrobka.com
Правила користування