Se a característica A estender B, a mistura de A fornecerá B precisamente mais o que A acrescenta ou estende. Por outro lado, se o traço A tiver uma auto-referência explicitamente digitada como B, a classe-mãe final também deverá misturar em B ou um tipo descendente de B (e misture-o primeiro , o que é importante).
Essa é a diferença mais importante. No primeiro caso, o tipo preciso de B é cristalizado no ponto A o estende. No segundo, o designer da classe pai decide qual versão de B é usada, no ponto em que a classe pai é composta.
Outra diferença é onde A e B fornecem métodos com o mesmo nome. Onde A estende B, o método de A substitui B. Onde A é misturado após B, o método de A simplesmente vence.
A auto-referência digitada oferece muito mais liberdade; o acoplamento entre A e B está solto.
ATUALIZAR:
Como você não tem certeza sobre o benefício dessas diferenças ...
Se você usa herança direta, cria a característica A que é B + A. Você definiu o relacionamento em pedra.
Se você usar uma auto-referência digitada, qualquer pessoa que queira usar sua característica A na classe C poderá
- Misture B e depois A em C.
- Misture um subtipo de B e depois A em C.
- Misture A em C, onde C é uma subclasse de B.
E esse não é o limite de suas opções, devido ao modo como o Scala permite instanciar uma característica diretamente com um bloco de código como seu construtor.
Quanto à diferença entre a vitória do método de A , porque A é o último da mistura, comparado a A que estende B, considere isso ...
Onde você mescla uma sequência de características, sempre que o método foo()
é chamado, o compilador vai para a última característica misturada para procurar e foo()
, se não for encontrado, ele percorre a sequência para a esquerda até encontrar uma característica que implemente foo()
e use naquela. A também tem a opção de chamar super.foo()
, que também percorre a sequência para a esquerda até encontrar uma implementação e assim por diante.
Portanto, se A tem uma auto-referência digitada para B e o escritor de A sabe que B implementa foo()
, A pode chamar super.foo()
sabendo que, se nada mais fornecer foo()
, B fará. No entanto, o criador da classe C tem a opção de remover qualquer outra característica na qual implementa foo()
, e A obterá isso.
Novamente, isso é muito mais poderoso e menos limitativo do que A estendendo B e chamando diretamente a versão de B de foo()
.