Como os mixins e traits são melhores que a herança múltipla simples?

51

C ++ possui múltiplas heranças simples, muitos projetos de linguagem proíbem-no como perigoso. Mas algumas linguagens como Ruby e PHP usam uma sintaxe estranha para fazer a mesma coisa e chamá-lo de mixins ou traits. Eu ouvi muitas vezes que mixins / traits são mais difíceis de usar do que simples herança múltipla.

O que os torna especificamente menos perigosos? Existe algo que não é possível com mixins / traits, mas possível com herança múltipla no estilo C ++? É possível encontrar o problema dos diamantes com eles?

Isto parece como se estivéssemos usando herança múltipla, mas apenas inventando desculpas que são mixins / traits para que possamos usá-los.

    
por Gherman 22.07.2014 / 22:32
fonte

1 resposta

31

Existem vários problemas com herança múltipla quando são usados com classes completas, mas todos eles giram em torno da ambigüidade .

A ambigüidade aparece de algumas maneiras diferentes:

  1. Se você tem duas classes base com o mesmo campo x , e o tipo derivado solicita x , o que ela obtém?
    • Se as duas variáveis x tiverem tipos incongruentes, você poderá inferir isso.
    • Se forem do mesmo tipo, você pode tentar mesclá-los na mesma variável.
    • Você sempre pode expô-los como nomes totalmente qualificados estranhos.
  2. Se você tem duas classes base com a mesma função f com assinaturas idênticas e alguém chama f , que é chamado?
    • E se as duas classes base compartilharem outro ancestral virtual comum (o problema do diamante).
    • E se a função tiver assinaturas diferentes, mas compatíveis?
  3. Quando você constrói uma classe com duas classes base, qual construtor das classes base é chamado primeiro? Quando você destrói o objeto, que é morto?
  4. Quando você coloca o objeto na memória, como você faz isso consistentemente?
  5. Como você lida com todos esses casos com 3 classes base? 10

E isso ignora coisas como despacho dinâmico, inferência de tipos, correspondência de padrões e outras coisas que eu conheço menos sobre as quais se tornam mais desafiadoras quando a linguagem suporta múltiplas heranças de classes completas.

Traits ou Mix-ins (ou interfaces, ou ...) são todas construções que especificamente limitam as capacidades de um tipo, de modo que não haja ambigüidade. Eles raramente possuem qualquer coisa eles mesmos. Isso permite que a composição dos tipos seja mais suave porque não há duas variáveis ou duas funções ... existe uma variável e uma referência; uma função e uma assinatura. O compilador sabe o que fazer.

A outra abordagem comum adotada é forçar o usuário a "construir" (ou misturar) seu tipo um de cada vez. Em vez de as classes base serem parceiros iguais no novo tipo, você adiciona um tipo a outro - substituindo tudo o que estava lá (geralmente com a sintaxe opcional para renomear e / ou expor novamente os bits substituídos).

Is there something that isn't possible with mixins/traits but possible with C++-style multiple inheritance?

Dependendo do idioma - geralmente torna-se problemático ou impossível mesclar implementações de funções e armazenamento para variáveis de múltiplas classes base e expô-las no tipo derivado.

Is it possible to run into diamond problem with them?

Ocasionalmente, variações menos graves aparecerão com base no seu idioma, mas geralmente não. O ponto inteiro dos traços é quebrar esse tipo de ambiguidade.

    
por 22.07.2014 / 23:15
fonte