为什么使用对象继承而不是mixins

时间:2011-09-16 23:28:36

标签: oop inheritance language-agnostic composition mixins

gist

支持继承而不是mixins的原因是什么

给出以下伪代码示例:

class Employee

class FullTimeEmployee inherits Employee

class PartTimeEmployee inherits Employee

// versus

class Employee

class WorksPartTime

class WorksFullTime

class FullTimeEmployee includes Employee, WorksFullTime
class PartTimeEmployee includes Employee, WorksPartTime

如果我们使用继承来构建对象,则类关系将被视为树,与mixin一样,类关系将被视为平面列表。

假设我们使用的语言

  • 允许使用非详细语法的mixin
  • 允许我们将FullTimeEmployee视为透明的EmployeeFullTime对象。

为什么我们要将类关系建立为树(继承)而不是平面列表(组合)?

树与列表的示例。

class Person

class Employee inherits Person

class FullTimeEmployee inherits Employee

//                      -> FullTimeEmployee
//  Person -> Employee
//                      -> PartTimeEmployee

class Person

class Employee includes Person

class FullTime

class FullTimeEmployee includes FullTime, Employee

//
// FullTimeEmployee = (FullTime, Employee, Person)
//

3 个答案:

答案 0 :(得分:3)

我认为在支持mixins的语言中,它实际上与使用(多个)继承相同。在这两种情况下,相同的类/对象上存在相同的方法/属性,两者都以完全相同的方式调用 - 没有实际的区别。我也假设在这种假设的语言中,你也可以从多个“类”中“扩展”。

如果这一切都是真的,那么在某种程度上它们是等价的并且问题没有意义 - 两者都不比另一种更好,因为它们是功能相同的。

以人类理解的方式,我认为大多数人都会考虑isA关系中的继承,以及用功能性装饰东西的混合。

如果你只能从一个'类'继承,那么显然mixins是一种获得多重继承的方法。

编辑 - 根据您的评论,这是好的,我会说假设语言的细节问题。我承认我的答案基于Sproutcore,这是一个Javascript框架,已经正式支持mixins和继承。在SC中,你可以做到

App.MyObject = SC.Object.extend({
  prop: 'prop',
  func: function(){
})

执行您期望的操作,它将propfunc放在MyObject的原型上,创建一个“类”,它可以包含子类。你也可以这样做

App.MyObject = SC.Object.extend(App.OtherObject, {
   // stuff
})

进行多重继承。然后你可以有像

这样的东西
CommonFunctionality = {
    // some methods
};

App.mixin(CommonFunctionality);

会将CommonFunctionality内容应用于App。如果app是命名空间(即{}),CommonFunctionality的方法将应用于该对象文字。如果它有意义,你也可以将CommonFunctionality应用于“类”,其方法将在原型上。如果你查看来源,你会看到

SC.extend = SC.mixin ;

所以在SC中,绝对没有区别,因为它们是相同的方法。

所以细节很重要 - 他们不必这样做,但他们确实这样做了,并且有影响。如果他们做得不同,那么当然会有不同的后果。

答案 1 :(得分:0)

您应该在必要时出现。如果你有一个1000行的大类,你发现自己在多个类中重复相同的东西,你可以在基类中封装一些逻辑,在mixins中封装其他逻辑。每个mixin都有一个有限的上下文,他们可能比他们应该知道更多,但他们只专注于某个任务。因此非常模块化。 好吧,我可以给你的最好的例子是Actor for a game,它有一些基础的继承,但使用mixins / plugins来共享功能。共享功能可以(直接来自源代码!):

var plugins = {
    SingleVisualEntity : SingleVisualEntity,
    JumpBehaviour      : JumpBehaviour,
    WeaponBehaviour    : WeaponBehaviour,
    RadarBehaviour     : RadarBehaviour,
    EnergyGatherer     : EnergyGatherer,
    LifeBarPlugin      : LifeBarPlugin,
    SelectionPlugin    : SelectionPlugin,
    UpgradePlugin      : UpgradePlugin,
    BrainPlugin        : BrainPlugin,
    PlanetObjectPlugin : PlanetObjectPlugin,
}

这最初是一个有+1000行的课程。

答案 2 :(得分:-1)

在设计时,我们会尽可能地模拟现实。

考虑is ahas a原则,FullTimeEmployee is an Employee具有额外(额外)功能,某些新事物{{1}在名为has an Employee的内容旁边,依此类推FullTime