Mixin срещу наследство

Каква е разликата между миксин и наследяване?


person Johnd    schedule 13.05.2009    source източник
comment
csswizardry.com/2014/11 /when-to-use-extend-when-to-use-a-mixin   -  person Usman I    schedule 01.02.2019


Отговори (9)


Миксинът обикновено се използва с множествено наследяване. Така че в този смисъл няма разлика.

Подробността е, че миксин рядко е полезен като самостоятелен обект.

Например, да кажем, че имате миксин с име ColorAndDimension, който добавя свойство цвят и ширина и височина.

Сега можете да добавите ColorAndDimension към, да речем, клас Shape, клас Sprite, клас Car и т.н. И всички те ще имат един и същ интерфейс (да кажем get/setColor, get/setHeight/Width и т.н.)

И така, в общия случай миксин Е наследяване. Но можете да спорите, че това е въпрос на ролята на класа в цялостния домейн дали миксинът е основен клас или просто миксин.


Редактиране - само за пояснение.

Да, миксин може да се счита, в днешния модерен жаргон, за интерфейс със свързано изпълнение. Това наистина е просто, старо, ежедневно множествено наследяване, използващо обикновен, стар, ежедневен клас. Това просто се случва да бъде специфично приложение на MI. Повечето езици не дават на mixin специален статус; това е просто клас, който е проектиран да бъде смесен, вместо да се използва самостоятелно.

person Will Hartung    schedule 13.05.2009

Каква е разликата между миксин и наследяване?

Mix-in е основен клас, от който можете да наследите, за да осигурите допълнителна функционалност. Пример за псевдокод:

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

Името "mix-in" показва, че е предназначено да бъде смесено с друг код. Като такъв, изводът е, че не бихте инстанцирали смесения клас сам. Следният обект няма данни и няма смисъл да се инстанцира, за да извика complex_method. (В такъв случай можете просто да дефинирате функция вместо клас.)

>>> obj = Mixin()

Често смесването се използва с други базови класове.

Следователно миксините са подмножество или специален случай на наследяване.

Предимствата на използването на смесване пред единичното наследяване са, че можете да напишете код за функционалността еднократно и след това да използвате същата функционалност в множество различни класове. Недостатъкът е, че може да се наложи да потърсите тази функционалност на други места, различни от мястото, където се използва, така че е добре да смекчите този недостатък, като я държите наблизо.

Аз лично открих смесване, необходимо за използване при единично наследяване, където тестваме модули на много подобен код, но тестовите случаи се инстанциират въз основа на тяхното наследяване на основен случай и единственият начин да запазим кода близо до ръка (и в същия модул), без да се забърквате с номерата на покритието, е да наследявате от обект и да наследявате дъщерните случаи както от универсалната база за тестови случаи, така и от персонализираната база, която се отнася само за тях.

Миксини в сравнение и контраст с абстрактни базови класове

И двата са форма на родителски клас, който не е предназначен да бъде инстанциран.

Миксин осигурява функционалност, но не може да я използва директно. Потребителят е предназначен да го използва чрез (под)клас.

Един абстрактен базов клас предоставя интерфейс, но без използваема функционалност. Потребителят е предназначен да създаде функционалността, извикана от интерфейса.

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

Тук сте възпрепятствани да създадете екземпляр на този обект, тъй като той изисква подклас за внедряване на функционалност с конкретен метод (въпреки че можете да получите достъп до функционалността от 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

В Python някои класове в модула abc са примери за родителски класове, които осигуряват функционалност чрез наследяване и абстрактни интерфейси, които трябва да бъдат имплементирани от подкласа. Тези идеи не се изключват взаимно.

Резюме

Казано по-просто, смесването е просто базов клас, който не бихте инстанцирали сам и обикновено се използва като вторичен базов клас при множествено наследяване.

person Aaron Hall    schedule 12.01.2015

mix-in е специфичен, ограничен случай на (множествено) наследяване, използван за целите на изпълнението; някои езици (напр. Ruby) го поддържат, без да поддържат обобщено множествено наследяване.

person Alex Martelli    schedule 13.05.2009

Mixin е абстрактна концепция и всичко, което отговаря на нейните изисквания, може да се счита за mixin.

Ето едно определение от Уикипедия.

В обектно-ориентираните езици за програмиране миксинът е клас, който съдържа методи за използване от други класове, без да е необходимо да бъде родителският клас на тези други класове. Как тези други класове получават достъп до методите на mixin зависи от езика. Миксините понякога се описват като „включени“, а не като „наследени“.

Накратко, ключовата разлика от наследяването е, че смесванията НЕ трябва да имат връзка „е-а“, както при наследяването.

От гледна точка на внедряването можете да го мислите като интерфейс с реализации. Например, абстрактен клас в Java може да се разглежда като mixin, ако Java поддържа множествено наследяване.

person Alex    schedule 06.05.2016
comment
Трудно ми е да разбера удебеленото изречение. Звучи като разликата (на B?) от A е, че то (B?) се нуждае от нещо като в A. Говорите за разлика или прилика? - person RayLuo; 17.10.2016
comment
@RayLuo Опа... Допуснах правописна грешка. Съжалявам, че ви обърквам. Смесването НЕ е необходимо да има връзка е-а - person Alex; 18.10.2016
comment
Java реализира смесване, като предлага метода по подразбиране в интерфейс. По този начин цялата комбинация от класове в тази функционалност ще бъде внедреният интерфейс. Това малко странно ли е? - person Lebecca; 19.11.2020

„Миксинът е фрагмент от клас в смисъл, че е предназначен да бъде съставен с други класове или миксини.“ -ДДЖ

Mixin е клас или кодов фрагмент, който не е предназначен за самостоятелна употреба, но вместо това трябва да го използвате вътре в друг клас. Или да го съставите като членско поле/променлива, или като кодов сегмент. Имам най-голямо излагане на по-късно. Това е малко по-добро от копиране и поставяне на шаблонен код.

Ето една страхотна статия за DDJ, която представя темата.

Half-Life 2 / "Source" SDK е чудесен пример за C++ mixins. В тази среда макросите дефинират значителни блокове код, които могат да бъдат добавени, за да придадат на класа специфичен „вкус“ или функция.

Погледнете примера на уики източника: Създаване на логически обект. В примерния код макросът DECLARE_CLASS може да се счита за миксин. Изходният SDK използва широко миксини за стандартизиране на кода за достъп до данни и приписване на поведение на обекти.

person Karl the Pagan    schedule 13.05.2009

Миксините се използват широко по начин, подобен на плъгини.

Те са еднакви, но в различен контекст всеки един от тях. Обикновено, когато говорим за наследяване, говорим за ЕДИНСТВЕНО наследяване, а mixin е конструкция, която позволява МНОЖЕСТВО наследяване.

Това е езикова конструкция, която е силно противоречива в света на ООП поради:

  • Неяснотата, че трябва да се разреши
  • Много от времето миксин класовете не работят сами по себе си и може да са в конфликт с други миксини
  • Това може да доведе до проблем с наследяването на диамант, при който два супер класа могат да наследяват от един и същи клас

Но това настрана, това е мощна конструкция, която се използва в различни езици и рамки, някои примери са:

person ggallovalle    schedule 16.10.2020

При множествено наследяване новият клас може да бъде съставен от множество суперкласове. Можете да извиквате само методи, дефинирани в някой от суперкласовете.

От друга страна, mixin е абстрактен подклас, който може да се използва за специализиране на поведението на различни родителски класове. Миксините могат да извикат метод (например sayHello(): String), въпреки че не дефинират такъв метод.

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

Както виждате, можете да извикате sayHello(), въпреки че не е дефинирано никъде. Ако добавите mixin M към клас C, C трябва да предостави метода sayHello().

person jk_    schedule 26.01.2011
comment
не съм сигурен в правилността на първото ви твърдение - класовете могат да дефинират свои собствени методи - person EugeneMi; 29.11.2013

Мисля, че е важно да се отбележи, че mixin не предполага наследяване. Според wikipedia Mixin е:

В обектно-ориентираните езици за програмиране миксинът е клас, който съдържа методи за използване от други класове, без да е необходимо да бъде родителският клас на тези други класове. Как тези други класове получават достъп до методите на mixin зависи от езика. Миксините понякога се описват като „включени“, а не като „наследени“.

По-конкретно, в език като perl, mixins могат да се добавят с помощта на модула 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'));
}

Които могат да бъдат смесени към всеки модул, съдържащ един или повече метод(и) наведнъж:

package MrT

use Mixins qw(pity);

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

sub _who_do_i_pity {
    return 'da foo!'
}

Тогава във вашия MrT модул може да се използва по следния начин:

use MrT;

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

Знам, че примерът е абсурден, но разбира смисъла...

person Lucas    schedule 15.04.2016

tl;dr

mixin и множественото наследяване имат една и съща форма. Но имат различна семантика: mixin има основните класове, осигуряващи изпълнението на функцията. За наследяване базовите класове предоставят интерфейс, а подкласът има имплементацията.

Но както и да е, композицията е за предпочитане пред mixin IMO

person del bao    schedule 26.03.2017