Se la caratteristica A si estende a B, quindi la miscelazione in A ti dà precisamente B più qualsiasi cosa A aggiunge o estende. Al contrario, se il tratto A ha un riferimento personale che viene esplicitamente digitato come B, allora la classe genitore finale deve anche mescolare B o un tipo discendente di B (e mescolarlo in prima , che è importante).
Questa è la differenza più importante. Nel primo caso, il tipo preciso di B viene cristallizzato nel punto A estendendolo. Nel secondo, il progettista della classe genitore decide quale versione di B viene utilizzata, nel punto in cui è composta la classe genitore.
Un'altra differenza è dove A e B forniscono metodi con lo stesso nome. Dove A estende B, il metodo di A sovrasta B's. Dove A viene mischiato dopo B, il metodo di A vince semplicemente.
Il riferimento automatico tipizzato ti dà molta più libertà; l'accoppiamento tra A e B è allentato.
UPDATE:
Poiché non sei chiaro sul vantaggio di queste differenze ...
Se usi l'ereditarietà diretta, crei la caratteristica A che è B + A. Hai impostato la relazione in pietra.
Se utilizzi un riferimento automatico digitato, chiunque desideri utilizzare la caratteristica A nella classe C potrebbe
- Mix B e poi A in C.
- Mescola un sottotipo di B e poi A in C
- Metti A in C, dove C è una sottoclasse di B.
E questo non è il limite delle loro opzioni, dato il modo in cui Scala ti permette di istanziare un tratto direttamente con un blocco di codice come suo costruttore.
Per quanto riguarda la differenza tra il metodo di A vincere , perché A è mischiato per ultimo, rispetto a A che estende B, considera questo ...
Dove mischiate una sequenza di tratti, ogni volta che viene invocato il metodo foo()
, il compilatore raggiunge l'ultima caratteristica mescolata per cercare foo()
, quindi (se non viene trovato), attraversa la sequenza a sinistra fino a quando non trova un tratto che implementa foo()
e lo usa. A ha anche la possibilità di chiamare super.foo()
, che attraversa anche la sequenza a sinistra finché trova un'implementazione, e così via.
Quindi se A ha un riferimento automatico scritto a B e il writer di A sa che B implementa foo()
, A può chiamare super.foo()
sapendo che se nient'altro fornisce foo()
, B lo farà. Tuttavia, il creatore della classe C ha la possibilità di eliminare qualsiasi altra caratteristica in cui implementa foo()
, e A lo otterrà.
Di nuovo, questo è molto più potente e meno limitante di A che estende B e chiama direttamente la versione di B di foo()
.