Mixin против наследования - PullRequest
83 голосов
/ 14 мая 2009

В чем разница между миксином и наследованием?

Ответы [ 8 ]

50 голосов
/ 14 мая 2009

Mix in обычно используется с множественным наследованием. Таким образом, в этом смысле «нет разницы».

Суть в том, что Mix in редко используется как отдельный объект.

Например, скажем, у вас есть имя Mix In "ColorAndDimension", которое добавляет свойство цвета, ширину и высоту.

Теперь вы можете добавить ColorAndDimension, скажем, в Shape Class, Sprite Class, Car Class и т. Д. И все они будут иметь одинаковый интерфейс (скажем, get / setColor, get / setHeight / Width и т. Д.)

Итак, в общем случае Mix in IS наследуется. Но вы можете утверждать, что вопрос о роли класса в общей области зависит от того, является ли Mix in «первичным» классом или просто Mix in.

Редактировать - просто чтобы уточнить.

Да, Mix In можно рассматривать в современном современном жаргоне как интерфейс со связанной реализацией. Это действительно просто старое, повседневное множественное наследование с использованием простого, старого, повседневного класса. Просто так происходит конкретное применение МИ. Большинство языков не дают смешивания В каком-либо особом статусе, это просто класс, который был разработан, чтобы быть «смешанным», а не использовался отдельно.

23 голосов
/ 12 января 2015

В чем разница между миксином и наследованием?

A mix-in - это базовый класс, от которого вы можете наследовать, чтобы обеспечить дополнительную функциональность. Пример псевдокода:

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

Название «mix-in» указывает, что оно предназначено для смешивания с другим кодом. Таким образом, вывод заключается в том, что вы не будете создавать экземпляр встроенного класса самостоятельно. Следующий объект не имеет данных, и нет смысла создавать его экземпляр для вызова complex_method. (В этом случае вы также можете просто определить функцию вместо класса.)

>>> obj = Mixin()

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

Следовательно, mixins - это подмножество или особый случай наследования.

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

Лично я нашел дополнение, необходимое для использования по одиночному наследованию, когда мы тестируем множество одинакового кода, но тестовые случаи создаются на основе их наследования базового случая и единственного способа сохранить Код под рукой (и в том же модуле), не связываясь с номерами покрытия, должен наследоваться от объекта, а дочерние случаи наследуются как от универсальной базы тестовых наборов, так и от пользовательской базы, которая применяется только к ним.

Mixins в сравнении и контрасте с абстрактными базовыми классами

Оба являются формой родительского класса, который не предназначен для создания экземпляра.

A 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 являются примерами родительских классов, которые предоставляют функциональность через наследование и абстрактные интерфейсы, которые должны быть реализованы подклассом. Эти идеи не являются взаимоисключающими.

Резюме

Проще говоря, встраиваемый модуль - это просто базовый класс, который вы не будете создавать самостоятельно, и обычно он используется как вторичный базовый класс в множественном наследовании.

18 голосов
/ 14 мая 2009

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

4 голосов
/ 06 мая 2016

Mixin - это абстрактное понятие, и все, что соответствует его требованию, может рассматриваться как миксин.

Вот определение из Википедии.

В объектно-ориентированных языках программирования миксин - это класс, который содержит методы для использования другими классами без необходимости быть родительским классом этих других классов. То, как эти другие классы получают доступ к методам миксина, зависит от языка. Миксины иногда описываются как «включенные», а не «унаследованные».

Короче говоря, ключевое отличие от наследования заключается в том, что встраиваемые модули НЕ должны иметь отношения "есть" как в наследовании.

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

3 голосов
/ 14 мая 2009

«Миксин - это фрагмент класса в том смысле, что он предназначен для объединения с другими классами или миксинами». -DDJ

Миксин - это класс или фрагмент кода, который не предназначен для автономного использования, но вместо этого вы должны использовать его внутри другого класса. Составьте его как поле / переменную-член или как сегмент кода. У меня больше всего воздействия на потом. Это немного лучше, чем копирование и вставка стандартного кода.

Вот отличная статья DDJ, которая вводит предмет.

Half-Life 2 / "Source" SDK является отличным примером C ++ mixin'ов. В этой среде макросы определяют значительные блоки кода, которые могут быть добавлены для придания классу определенного «вкуса» или функции.

Посмотрите на пример Source wiki: Создание логического объекта . В примере кода макрос DECLARE_CLASS можно считать миксином. Source SDK широко использует миксины, чтобы стандартизировать код доступа к данным и приписывать поведение объектам.

0 голосов
/ 26 марта 2017

ТЛ; др

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

Но в любом случае, композиция предпочтительнее, чем миксин ИМО

0 голосов
/ 15 апреля 2016

Я думаю, важно отметить, что mixin не подразумевает наследование . Согласно википедии, Mixin это:

В объектно-ориентированных языках программирования mixin - это класс, который содержит методы для использования другими классами без необходимости быть родительский класс тех других классов. Как получают эти другие классы доступ к методам миксина зависит от языка. Mixins являются иногда описывается как «включенный», а не «унаследованный».

В частности, на таких языках, как perl, миксины можно добавлять с помощью модуля 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();

Я знаю, что это абсурдный пример, но суть в этом ...

0 голосов
/ 26 января 2011

При множественном наследовании новый класс может состоять из нескольких суперклассов. Вы можете вызывать только методы, определенные в любом из суперклассов.

С другой стороны, mixin - это абстрактный подкласс, который может быть использован для специализации вида различных родительских классов. Миксины могут вызывать метод (например, sayHello(): String), даже если они не определяют такой метод.

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

Как видите, вы можете позвонить sayHello(), хотя он нигде не определен. Если вы добавите mixin M в класс C, C должен обеспечить метод sayHello().

...