Mixin vs herança


Respostas:


66

Um mixin é normalmente usado com herança múltipla. Portanto, nesse sentido, "não há diferença".

O detalhe é que um mixin raramente é útil como um objeto independente.

Por exemplo, digamos que você tenha um mixin chamado "ColorAndDimension", que adiciona uma propriedade de cor e largura e altura.

Agora, você poderia adicionar ColorAndDimension a uma, digamos, classe Shape, uma classe Sprite, uma classe Car, etc. E todos eles terão a mesma interface (digamos get / setColor, get / setHeight / Width etc.)

Portanto, no caso genérico, uma herança do mixin IS. Mas você pode argumentar que é uma questão do papel da classe no domínio geral se um mixin é uma classe "primária" ou simplesmente um mixin.


Editar - apenas para esclarecer.

Sim, um mixin pode ser considerado, no jargão moderno de hoje, uma interface com uma implementação associada. É realmente uma herança múltipla simples, antiga e cotidiana, usando uma classe comum, antiga e cotidiana. Acontece que é uma aplicação específica de MI. A maioria dos idiomas não confere nenhum status especial ao mix; é apenas uma classe que foi projetada para ser "misturada", em vez de usada de forma independente.


29

Qual é a diferença entre um mixin e herança?

Um mix-in é uma classe base da qual você pode herdar para fornecer funcionalidade adicional. Exemplo de pseudocódigo:

class Mixin:
    def complex_method(self):
        return complex_functionality(self)

O nome "mix-in" indica que se destina a ser misturado com outro código. Como tal, a inferência é que você não instanciaria a classe mix-in por conta própria. O objeto a seguir não tem dados e não faz sentido instanciá-lo para chamar complex_method. (Você também pode definir uma função em vez de uma classe nesse caso.)

>>> obj = Mixin()

Freqüentemente, o mix-in é usado com outras classes básicas.

Portanto, os mixins são um subconjunto, ou caso especial, de herança.

As vantagens de usar um mix-in em vez de herança única são que você pode escrever código para a funcionalidade uma vez e, em seguida, usar a mesma funcionalidade em várias classes diferentes. A desvantagem é que você pode precisar procurar essa funcionalidade em outros lugares além de onde ela é usada, portanto, é bom atenuar essa desvantagem mantendo-a por perto.

Eu pessoalmente encontrei uma combinação necessária para usar em herança única, onde estamos testando a unidade de muitos códigos semelhantes, mas os casos de teste são instanciados com base em sua herança de um caso base, e a única maneira de manter o código próximo de mão (e no mesmo módulo), sem mexer com os números de cobertura, é herdar do objeto e fazer com que os casos filhos herdem tanto a base de caso de teste universal quanto a base customizada que se aplica apenas a eles.

Mixins em comparação e contraste com classes básicas abstratas

Ambos são uma forma de classe pai que não se destina a ser instanciada.

Um mixin fornece funcionalidade, mas não pode usá-la diretamente. Um usuário deve usá-lo por meio de uma (sub) classe.

Uma classe base abstrata fornece uma interface, mas sem funcionalidade utilizável. Um usuário deve criar a funcionalidade chamada pela interface.

class Abstraction(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def complex_method(self):
        return complex_functionality(self)

Aqui você é impedido de instanciar este objeto porque ele requer uma subclasse para implementar a funcionalidade com um método concreto (embora você possa acessar a funcionalidade dentro de super()):

>>> obj = Abstraction()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Abstraction with
abstract methods complex_method

Em Python, algumas classes no abcmódulo são exemplos de classes pai que fornecem funcionalidade por meio de herança e interfaces abstratas que devem ser implementadas pela subclasse. Essas ideias não são mutuamente exclusivas.

Resumo

Simplificando, um mix-in é apenas uma classe base que você não instanciaria por conta própria e normalmente usada como uma classe base secundária em herança múltipla.


18

mix-in é um caso específico e restrito de herança (múltipla) usada para fins de implementação; algumas linguagens (por exemplo, Ruby) o suportam sem suportar herança múltipla generalizada.


7

Mixin é um conceito abstrato e qualquer coisa que atenda a seus requisitos pode ser considerado um mixin.

Aqui está uma definição da Wikipedia.

Em linguagens de programação orientadas a objetos, um mixin é uma classe que contém métodos para uso por outras classes sem ter que ser a classe pai dessas outras classes. Como essas outras classes obtêm acesso aos métodos do mixin depende da linguagem. Mixins às vezes são descritos como sendo "incluídos" em vez de "herdados".

Resumindo, a principal diferença de uma herança é que os mix-ins NÃO precisam ter um relacionamento "é um" como na herança.

Do ponto de vista da implementação, você pode pensar nisso como uma interface com as implementações. Por exemplo, uma classe abstrata em Java poderia ser considerada um mixin se Java suportasse herança múltipla.


Estou tendo dificuldade em entender a frase ousada. Parece que "a diferença (de B?) De A é que (B?) Precisa de algo como em A". Você está falando sobre diferença ou semelhança?
RayLuo,

@RayLuo Opa ... cometi um erro de digitação. Desculpe confundi-lo. Mix-ins NÃO precisa ter um relacionamento "é um"
Alex

3

"Um mixin é um fragmento de uma classe no sentido de que se destina a ser composto com outras classes ou mixins." -DDJ

Um mixin é uma classe ou fragmento de código que não se destina a uso independente, mas em vez disso, você deve usá-lo dentro de outra classe. Seja compondo como um campo / variável membro ou como um segmento de código. Eu tenho mais exposição ao último. É um pouco melhor do que copiar e colar o código clichê.

Aqui está um ótimo artigo DDJ que introduz o assunto.

O SDK do Half-Life 2 / "Source" é um ótimo exemplo de mixins C ++. Nesse ambiente, as macros definem blocos consideráveis ​​de código que podem ser adicionados para dar à classe um "sabor" ou recurso específico.

Veja o exemplo do wiki de origem: Autoria de uma entidade lógica . No código de exemplo, a macro DECLARE_CLASS pode ser considerada um mixin. Source SDK usa mixins extensivamente para padronizar o código de acesso a dados e atribuir comportamentos às entidades.


0

Com herança múltipla, a nova classe pode ser composta de várias superclasses. Você pode chamar apenas métodos definidos em qualquer uma das superclasses.

Por outro lado, mixin é uma subclasse abstrata que pode ser usada para especializar o beavior de uma variedade de classes pai. Mixins podem chamar um método (por exemplo sayHello(): String) mesmo que não definam tal método.

mixin M {
    name: String
    defmethod greetings() { print sayHello() + " " + name}
}

Como você vê, você pode chamar sayHello()mesmo que não esteja definido em nenhum lugar. Se você adicionar o mixin Mà classe C, o Cdeve fornecer o sayHello()método.


1
não tenho certeza sobre a exatidão de sua primeira instrução - as classes podem definir seus próprios métodos
EugeneMi

0

Eu acho importante notar que o mixin não implica em herança . De acordo com a wikipedia, um Mixin é:

Em linguagens de programação orientadas a objetos, um mixin é uma classe que contém métodos para uso por outras classes sem ter que ser a classe pai dessas outras classes. Como essas outras classes obtêm acesso aos métodos do mixin depende da linguagem. Mixins às vezes são descritos como sendo "incluídos" em vez de "herdados".

Especificamente, em uma linguagem como perl, mixins podem ser adicionados usando o módulo Exportador:

package Mixins;

use Exporter qw(import);
our @EXPORT_OK = qw(pity);

# assumes it will be mixed-in to a class with a _who_do_i_pity method
sub pity {
    my ($self) = @_;
    printf("I pity %s\n", $self->_who_do_i_pity('da foo'));
}

Que pode ser misturado a qualquer módulo contendo um, ou mais, método (s) de cada vez:

package MrT

use Mixins qw(pity);

sub new {
    return bless({}, shift);
}

sub _who_do_i_pity {
    return 'da foo!'
}

Então, em seu MrTmódulo pode ser usado da seguinte forma:

use MrT;

MrT->new()->pity();

Eu sei que é um exemplo absurdo, mas, ele mostra o que quero dizer ...


0

tl; dr

o mixin e a herança múltipla têm a mesma forma. Mas tem uma semântica diferente: o mixin tem as classes básicas que fornecem a implementação da função. Para herança, as classes básicas fornecem interface e a subclasse possui a implementação.

Mas de qualquer maneira, a composição é preferível ao mixin IMO

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.