Mixin vs héritage


Réponses:


66

Un mixin est généralement utilisé avec l'héritage multiple. Donc, dans ce sens, il n'y a «aucune différence».

Le détail est qu'un mixin est rarement utile en tant qu'objet autonome.

Par exemple, supposons que vous ayez un mixin nommé "ColorAndDimension", qui ajoute une propriété de couleur, une largeur et une hauteur.

Maintenant, vous pouvez ajouter ColorAndDimension à une classe, disons, Shape, une classe Sprite, une classe Car, etc. Et ils auront tous la même interface (disons get / setColor, get / setHeight / Width, etc.)

Donc, dans le cas générique, un héritage mixin IS. Mais vous pouvez argumenter que c'est une question de rôle de la classe dans le domaine global de savoir si un mixin est une classe "primaire" ou simplement un mixin.


Edit - juste pour clarifier.

Oui, un mixin peut être considéré, dans le jargon moderne d'aujourd'hui, comme une interface avec une implémentation associée. Il s'agit vraiment d'un héritage multiple ordinaire, ancien et quotidien utilisant une classe ordinaire, ancienne et quotidienne. Il s'agit simplement d'une application spécifique de l'IM. La plupart des langues ne donnent aucun statut spécial à un mixage; c'est juste une classe qui a été conçue pour être "mélangée", plutôt que utilisée de manière autonome.


29

Quelle est la différence entre un mixin et un héritage?

Un mix-in est une classe de base dont vous pouvez hériter pour fournir des fonctionnalités supplémentaires. Exemple de pseudocode:

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

Le nom «mix-in» indique qu'il est destiné à être mélangé avec un autre code. En tant que tel, on en déduit que vous n'instancieriez pas la classe de mixage seule. L'objet suivant n'a pas de données et il n'a aucun sens de l'instancier pour appeler complex_method. (Vous pouvez aussi simplement définir une fonction au lieu d'une classe dans ce cas.)

>>> obj = Mixin()

Le mix-in est fréquemment utilisé avec d'autres classes de base.

Par conséquent, les mixins sont un sous-ensemble, ou un cas particulier, d'héritage.

Les avantages de l'utilisation d'un mix-in par rapport à l'héritage unique sont que vous pouvez écrire du code pour la fonctionnalité une fois, puis utiliser la même fonctionnalité dans plusieurs classes différentes. L'inconvénient est que vous devrez peut-être rechercher cette fonctionnalité ailleurs que là où elle est utilisée, il est donc bon d'atténuer cet inconvénient en la gardant à proximité.

J'ai personnellement trouvé un mix-in nécessaire à utiliser sur un héritage unique où nous testons beaucoup de code similaire, mais les cas de test sont instanciés en fonction de leur héritage d'un cas de base, et le seul moyen de garder le code proche à hand (et dans le même module), sans jouer avec les numéros de couverture, est d'hériter de l'objet, et de faire hériter les cas enfants de la base de cas de test universelle et de la base personnalisée qui ne s'applique qu'à eux.

Mixins en comparaison et contraste avec les classes de base abstraites

Les deux sont une forme de classe parente qui n'est pas destinée à être instanciée.

Un mixin fournit des fonctionnalités, mais ne peut pas les utiliser directement. Un utilisateur est destiné à l'utiliser via une (sous) classe.

Une classe de base abstraite fournit une interface, mais sans fonctionnalité utilisable. Un utilisateur est destiné à créer la fonctionnalité appelée par l'interface.

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

Ici, vous ne pouvez pas instancier cet objet car il nécessite une sous-classe pour implémenter des fonctionnalités avec une méthode concrète (bien que vous puissiez accéder à la fonctionnalité à partir 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

En Python, certaines classes du abc module sont des exemples de classes parentes qui fournissent à la fois des fonctionnalités via l'héritage et des interfaces abstraites qui doivent être implémentées par la sous-classe. Ces idées ne s'excluent pas mutuellement.

Résumé

En termes simples, un mix-in n'est qu'une classe de base que vous n'instancierez pas seule, et généralement utilisée comme classe de base secondaire dans l'héritage multiple.


18

le mix-in est un cas spécifique et restreint d'héritage (multiple) utilisé à des fins d'implémentation; certains langages (par exemple Ruby) le supportent sans prendre en charge l'héritage multiple généralisé.


7

Mixin est un concept abstrait et tout ce qui répond à ses exigences peut être considéré comme un mixin.

Voici une définition de Wikipedia.

Dans les langages de programmation orientés objet, un mixin est une classe qui contient des méthodes à utiliser par d'autres classes sans avoir à être la classe parente de ces autres classes. La manière dont ces autres classes accèdent aux méthodes du mixin dépend de la langue. Les mixins sont parfois décrits comme étant "inclus" plutôt que "hérités".

En bref, la principale différence avec un héritage est que les mix-ins n'ont PAS besoin d'avoir une relation «est-un» comme dans l'héritage.

Du point de vue de l'implémentation, vous pouvez le penser comme une interface avec les implémentations. Par exemple, une classe abstraite en Java peut être considérée comme un mixin si Java prend en charge l'héritage multiple.


J'ai du mal à comprendre la phrase en gras. Cela ressemble à "la différence (de B?) De A est qu'il (B?) A besoin de quelque chose comme en A". Parlez-vous de différence ou de similitude?
RayLuo

@RayLuo Oups ... J'ai fait une faute de frappe. Désolé de vous confondre. Les mix-ins n'ont PAS besoin d'avoir une relation "is-a"
Alex

3

"Un mixin est un fragment d'une classe dans le sens où il est destiné à être composé avec d'autres classes ou mixins." -DDJ

Un mixin est une classe ou un fragment de code qui n'est pas destiné à une utilisation autonome, mais à la place vous êtes censé l'utiliser dans une autre classe. Soit en le composant en tant que champ / variable membre, soit en tant que segment de code. Je suis le plus exposé au plus tard. C'est un peu mieux que de copier-coller du code standard.

Voici un excellent article DDJ qui introduit le sujet.

Le SDK Half-Life 2 / "Source" est un excellent exemple de mixins C ++. Dans cet environnement, les macros définissent des blocs de code importants qui peuvent être ajoutés pour donner à la classe une "saveur" ou une fonctionnalité spécifique.

Regardez l'exemple du wiki source: création d'une entité logique . Dans l'exemple de code, la macro DECLARE_CLASS peut être considérée comme un mixin. Le SDK source utilise largement les mixins pour standardiser le code d'accès aux données et attribuer des comportements aux entités.


0

Avec l'héritage multiple, une nouvelle classe peut être composée de plusieurs superclasses. Vous ne pouvez appeler que les méthodes définies dans l'une des superclasses.

D'autre part, mixin est une sous-classe abstraite qui peut être utilisée pour spécialiser le beavior d'une variété de classes parentes. Les mixins peuvent appeler une méthode (par exemple sayHello(): String) même s'ils ne définissent pas une telle méthode.

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

Comme vous le voyez, vous pouvez appeler sayHello()même s'il n'est défini nulle part. Si vous ajoutez le mixin Mà la classe C, le Cdoit fournir la sayHello()méthode.


1
pas sûr de l'exactitude de votre première déclaration - les classes peuvent définir leurs propres méthodes
EugeneMi

0

Je pense qu'il est important de noter que le mixin n'implique pas l' héritage . Selon wikipedia, un Mixin est:

Dans les langages de programmation orientés objet, un mixin est une classe qui contient des méthodes à utiliser par d'autres classes sans avoir à être la classe parente de ces autres classes. La manière dont ces autres classes accèdent aux méthodes du mixin dépend de la langue. Les mixins sont parfois décrits comme étant "inclus" plutôt que "hérités".

Plus précisément, dans un langage comme perl, des mixins peuvent être ajoutés à l'aide du module Exporter:

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'));
}

Qui peut être intégré à n'importe quel module contenant une ou plusieurs méthode (s) à la fois:

package MrT

use Mixins qw(pity);

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

sub _who_do_i_pity {
    return 'da foo!'
}

Ensuite, dans votre MrTmodule peut être utilisé ainsi:

use MrT;

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

Je sais que c'est un exemple absurde, mais ça fait passer le message ...


0

tl; dr

mixin et l'héritage multiple ont la même forme. Mais ayez une sémantique différente: mixin a les classes de base qui fournissent l'implémentation de la fonction. Pour l'héritage, les classes de base fournissent l'interface et la sous-classe a l'implémentation.

Mais de toute façon, la composition est préférée au mixin IMO

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.