В чем разница между миксином и наследованием?
Ответы:
Примесь обычно используется с множественным наследованием. Так что в этом смысле «никакой разницы».
Деталь в том, что миксин редко бывает полезен как отдельный объект.
Например, предположим, что у вас есть миксин с именем «ColorAndDimension», который добавляет свойство цвета, а также ширину и высоту.
Теперь вы можете добавить ColorAndDimension, скажем, в класс Shape, класс Sprite, класс Car и т. Д. И все они будут иметь одинаковый интерфейс (скажем, get / setColor, get / setHeight / Width и т. Д.)
Итак, в общем случае примесь является наследованием IS. Но вы можете утверждать, что это вопрос роли класса в общем домене относительно того, является ли миксин "основным" классом или просто миксином.
Редактировать - просто для уточнения.
Да, миксин на современном современном жаргоне можно рассматривать как интерфейс со связанной реализацией. На самом деле это обычное, старое, повседневное множественное наследование с использованием простого, старого, повседневного класса. Это просто конкретное приложение MI. Большинство языков не придают миксинам особого статуса; это просто класс, который был разработан для «смешивания», а не для использования отдельно.
В чем разница между миксином и наследованием?
Смесь в базовый класс вы можете наследовать от предоставления дополнительной функциональности. Пример псевдокода:
class Mixin:
def complex_method(self):
return complex_functionality(self)
Название «mix-in» указывает, что оно предназначено для смешивания с другим кодом. Таким образом, подразумевается, что вы не будете создавать экземпляр класса подмешивания самостоятельно. Следующий объект не имеет данных, и нет смысла создавать его экземпляр для вызова complex_method. (В этом случае вы можете просто определить функцию вместо класса.)
>>> obj = Mixin()
Часто смесь используется с другими базовыми классами.
Следовательно, миксины - это подмножество или особый случай наследования.
Преимущество смешанного наследования перед одиночным наследованием состоит в том, что вы можете написать код для функциональности один раз, а затем использовать ту же функциональность в нескольких разных классах. Недостатком является то, что вам может потребоваться поискать эту функциональность в других местах, а не там, где она используется, поэтому хорошо смягчить этот недостаток, оставив ее поблизости.
Я лично нашел смесь, необходимую для использования при одиночном наследовании, где мы тестируем много аналогичного кода, но тестовые примеры создаются на основе их наследования базового случая, и это единственный способ сохранить код близко к hand (и в том же модуле), не вмешиваясь в числа покрытия, должен наследовать от объекта, а дочерние кейсы наследуются как от универсальной базы тестовых примеров, так и от настраиваемой базы, которая применяется только к ним.
Оба являются формой родительского класса, который не предназначен для создания экземпляров.
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
модуле являются примерами родительских классов, которые обеспечивают функциональность через наследование и абстрактные интерфейсы, которые должны быть реализованы подклассом. Эти идеи не исключают друг друга.
Проще говоря, подмешивание - это просто базовый класс, который вы не создадите самостоятельно, и обычно используется как вторичный базовый класс при множественном наследовании.
подмешивание - это конкретный, ограниченный случай (множественного) наследования, используемый для целей реализации; некоторые языки (например, Ruby) поддерживают его без поддержки обобщенного множественного наследования.
Mixin - это абстрактное понятие, и все, что соответствует его требованиям, можно рассматривать как миксин.
Вот определение из Википедии.
В объектно-ориентированных языках программирования миксин - это класс, который содержит методы для использования другими классами, не являясь родительским классом этих других классов. Как эти другие классы получают доступ к методам миксина, зависит от языка. Миксины иногда описываются как «включенные», а не «унаследованные».
Короче говоря, ключевое отличие от наследования состоит в том, что примешивание НЕ обязательно должно иметь отношение «есть», как в наследовании.
С точки зрения реализации вы можете рассматривать его как интерфейс с реализациями. Например, абстрактный класс в Java можно рассматривать как миксин, если Java поддерживает множественное наследование.
«Примесь - это фрагмент класса в том смысле, что он предназначен для создания с другими классами или миксинами». -DDJ
Примесь - это класс или фрагмент кода, который не предназначен для автономного использования, но вместо этого вы должны использовать его внутри другого класса. Либо составьте его как поле / переменную члена, либо как сегмент кода. Я больше всего знаком с последним. Это немного лучше, чем копирование и вставка шаблонного кода.
Вот отличная статья DDJ, которая знакомит с этой темой.
Half-Life 2 / "Source" SDK - отличный пример миксинов C ++. В этой среде макросы определяют значительные блоки кода, которые могут быть добавлены, чтобы придать классу особый «вкус» или функцию.
Взгляните на пример исходной вики: Создание логической сущности . В примере кода макрос DECLARE_CLASS можно рассматривать как миксин. Source SDK широко использует миксины для стандартизации кода доступа к данным и описания поведения сущностей.
При множественном наследовании новый класс может состоять из нескольких суперклассов. Вы можете вызывать только методы, определенные в любом из суперклассов.
С другой стороны, mixin - это абстрактный подкласс, который можно использовать для специализации поведения множества родительских классов. Миксины могут вызывать метод (например sayHello(): String
), даже если они не определяют такой метод.
mixin M {
name: String
defmethod greetings() { print sayHello() + " " + name}
}
Как видите, вы можете позвонить, sayHello()
даже если это нигде не определено. Если вы добавите миксин M
в класс C
, он C
должен предоставить sayHello()
метод.
Думаю, важно отметить, что миксин не подразумевает наследования . Согласно Википедии, Mixin - это:
В объектно-ориентированных языках программирования миксин - это класс, который содержит методы для использования другими классами, не являясь родительским классом этих других классов. Как эти другие классы получают доступ к методам миксина, зависит от языка. Миксины иногда описываются как «включенные», а не «унаследованные».
В частности, в таком языке, как 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();
Я знаю, что это абсурдный пример, но он уловил суть ...
tl; dr
примесь и множественное наследование имеют одинаковую форму. Но имеют разную семантику: в миксине базовые классы обеспечивают реализацию функции. Для наследования базовые классы предоставляют интерфейс, а подкласс имеет реализацию.
Но в любом случае композиция предпочтительнее миксина. IMO