Якщо ознака A поширюється на B, то змішування в A дає точніше B плюс те, що додає або розширює A. На відміну від цього, якщо ознака A має власне посилання, яке явно вводиться як B, то кінцевий батьківський клас також повинен змішуватися з B або низхідним типом B (і змішувати його спочатку , що важливо).
Це найважливіша відмінність. У першому випадку точний тип В кристалізується в точці А, яка розширює його. По-друге, дизайнер батьківського класу отримує рішення про те, яку версію B використовуватиме, в точці, де складається батьківський клас.
Інша відмінність полягає в тому, де A і B надають методи з однойменною назвою. Якщо A поширюється на B, метод A переосмислює B. Якщо A замішується після B, метод A просто виграє.
Набране самонавіювання дає вам набагато більше свободи; з'єднання між А і В є вільним.
ОНОВЛЕННЯ:
Оскільки вам не зрозуміло користь цих відмінностей ...
Якщо ви використовуєте пряме успадкування, ви створюєте ознаку A, яка є B + A. Ви встановили відносини в камені.
Якщо ви використовуєте набрану самостійну посилання, будь-хто, хто хоче використовувати вашу ознаку А в класі С, міг би
- Змішайте B, а потім A в C.
- Змішайте підтип B, а потім A в C.
- Змішайте A в C, де C є підкласом B.
І це не межа їх можливостей, враховуючи те, як Scala дозволяє інстанціювати ознаку безпосередньо з блоком коду як її конструктором.
Щодо різниці між виграшним методом A , оскільки A змішаний останнім, порівняно з A, що розширюється B, врахуйте це ...
Якщо ви змішуєте в послідовності ознак, кожного разу, коли використовується метод foo(), компілятор переходить до останньої ознаки, змішаної, щоб шукати foo(), тоді (якщо її не знайдено), вона переміщає послідовність зліва, поки не знайде ознаку, яка реалізує foo()та використовує що. Також є можливість викликати super.foo(), який також проходить послідовність зліва, поки не знайде реалізацію тощо.
Отже, якщо A має введене само посилання на B, і письменник A знає, що B реалізує foo(), A може зателефонувати, super.foo()знаючи, що якщо нічого іншого не передбачено foo(), B буде. Однак у творця класу C є можливість скинути будь-яку іншу ознаку, в якій реалізується foo(), і A отримає це замість цього.
Знову ж , це набагато більш потужні і менш жорсткі обмеження , ніж витягнута B і прямий виклик версії B по foo().