Mixin vs 继承

混合和继承之间的区别是什么?

40422 次浏览

Mix-in 是一种用于实现目的的特定的、受限制的(多重)继承,有些语言(比如 Ruby)不支持通用的多重继承。

Mixin 通常与多重继承一起使用,因此,在这个意义上,“没有区别”。

细节是,混合函数很少作为独立对象使用。

例如,假设您有一个名为“ ColorAndScale”的混合文件,它添加了一个颜色属性以及宽度和高度。

现在,您可以向一个,比如说,形状类,雪碧类,汽车类,等等,添加 ColorAndScale。它们都有相同的接口(例如 get/setColor、 get/setHeight/Width 等)

因此,在一般情况下,混合 IS 继承。但是您可以争辩说,这是一个关于类在整个域中的角色的问题,即混合是一个“主”类还是一个简单的混合。


编辑,澄清一下。

是的,在今天的现代术语中,混合可以被认为是具有相关实现的接口。它真的只是普通的,老式的,日常的多重继承使用普通的,老式的,日常的课程。它恰好是 MI 的一个特定应用。大多数语言没有赋予混合类任何特殊的状态; 它只是一个被设计为“混合”的类,而不是独立使用的类。

在某种意义上,混合类是类的一个片段,因为它打算由其他类或混合类组成DDJ

Mixin 是一个类或代码片段,它不是为了独立使用而设计的,而是应该在另一个类中使用它。要么将其作为成员字段/变量组合,要么作为代码段组合。我接触的最多的是后者。这比复制粘贴样板代码要好一点。

这里有一篇介绍这个主题的很棒的 DDJ 文章。

半条命2/“ Source”SDK 是 C + + 混合语言的一个很好的例子。在这种环境中,宏定义了大量的代码块,可以添加这些代码块来为类提供特定的“风格”或特性。

看看 Source wiki 的例子: 创作逻辑实体。在示例代码中,DECLARE _ CLASS 宏可以被视为一个 mix In。SourceSDK 广泛地使用 Mixin 来标准化数据访问代码并将行为归因于实体。

有了多重继承,新类可以由多个超类组成。只能调用在任何超类中定义的方法。

另一方面,Mixin 是一个抽象子类,可用于专门化各种父类的行为。混合函数可以调用方法(例如 sayHello(): String) ,即使它们没有定义这样的方法。

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

正如您所看到的,您可以调用 sayHello(),即使它在任何地方都没有定义。如果向类 C添加 MixinM,则 C应该提供 sayHello()方法。

混合和继承之间的区别是什么?

混合是一个基类,您可以从中继承以提供附加功能:

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

名称“ mix-in”表明它打算与其他代码混合在一起。因此,推论是您不会自己实例化 mix-in 类。下面的对象没有数据,实例化它来调用 plex _ method 是没有意义的。(在这种情况下,您最好只定义一个函数而不是一个类。)

>>> obj = Mixin()

混合类通常与其他基类一起使用。

因此 Mixin 是继承的子集或特殊情况。

与单一继承相比,混合使用的优势在于,您可以为该功能编写一次代码,然后在多个不同的类中使用相同的功能。缺点是您可能需要在使用它的地方以外的其他地方寻找该功能,因此最好将它放在附近以减轻这一缺点。

我个人发现在单一继承上使用混合是必要的,我们单元测试了很多相似的代码,但是测试用例是基于它们对基本用例的继承而实例化的,保持代码近在咫尺(并且在同一个模块中)的唯一方法是不干扰覆盖率数字,就是从对象继承,并且让子用例继承来自通用测试用例基础和仅适用于它们的自定义基础。

混合类与抽象基类的比较与对比

两者都是父类的一种形式,不打算实例化。

< em > 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模块中的一些类是父类的例子,它们都通过继承和必须由子类实现的抽象接口提供功能。这些想法并不相互排斥。

摘要

简单地说,mix-in 只是一个基类,您不会自己实例化它,它通常用作多重继承中的辅助基类。

我认为值得注意的是,混音并不意味着 继承遗产。根据维基百科,Mixin是:

在面向对象程序设计语言中混合类是指 包含供其他类使用的方法,而不必成为 那些其他类的父类。那些其他类如何获得 对混合函数方法的访问取决于语言 有时被描述为“包含”而不是“继承”。

具体来说,在 perl 这样的语言中,可以使用 Exporter 模块添加 Mixin:

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();

我知道这个例子很荒谬,但是,这个例子说明了..。

Mixin 是一个抽象的概念,任何符合其要求的东西都可以被看作是一个混合体。

下面是来自维基百科的定义。

在面向对象程序设计语言中,Mixin 是一个包含其他类使用的方法的类,而不必成为其他类的父类。这些其他类如何获得对混合函数方法的访问取决于语言。混合有时被描述为“包含”而不是“继承”。

简而言之,与继承的关键区别在于 mix-In 不需要像继承中那样具有“ is-a”关系。

从实现的角度来看,您可以将其视为具有实现的接口。例如,如果 Java 支持多重继承,那么 Java 中的一个抽象类可以被看作一个 Mixin。

博士

混合蛋白和多重继承蛋白的形式是一样的。但具有不同的语义: 混合有基本类提供的函数实现。对于继承,基类提供接口,子类具有实现。

但无论如何,组成是首选的混合在国际海事组织

混合广泛使用在一个更“插件”样的方式。

它们是相同的,但是在不同的上下文中,每一个都是不同的。通常当我们谈论继承的时候,我们谈论的是单一继承,混合是一种允许多重继承的结构。

这是一种语言结构,在面向对象程序设计的世界中备受争议,因为:

  • 必须解决的模棱两可的问题
  • 很多时候,“ Mixin”类不能独立工作,并且可能与其他 Mixin 发生冲突
  • 它可能导致“菱形继承问题”,即两个超类可以从同一个类继承

除此之外,这是一个在各种语言和框架中使用的强大构造,例如: