Ray*_*nos 5 language-agnostic oop inheritance composition mixins
有利于继承而不是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
Run Code Online (Sandbox Code Playgroud)
如果我们使用继承来构建对象,则类关系将被视为树,与mixin一样,类关系将被视为平面列表.
假设我们使用的语言
FullTimeEmployeea Employee和FullTime对象.我们为什么要建立我们的类关系作为树(继承)而不是平面列表(组合)?
树与列表的示例.
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)
//
Run Code Online (Sandbox Code Playgroud)
我认为在支持 mixins 的语言中,它实际上与使用(多重)继承相同。在这两种情况下,相关的类/对象上存在相同的方法/属性,两者的调用方式完全相同——没有实际区别。我还假设在这种假设的语言中,您也可以从多个“类”进行“扩展”。
如果这一切都是真的,那么在某种程度上它们是等效的,并且这个问题没有意义——没有一个比另一个更好,因为它们在功能上是等效的。
从人类理解的角度来看,我认为大多数人从isA关系的角度考虑继承,从装饰功能的角度考虑混入。
如果您只能从一个“类”继承,那么显然 mixins 是一种获得多重继承的方法。
编辑——根据你的评论,这些评论很好,我想说假设语言的细节很重要。我承认我的答案是基于 Sproutcore,它是一个 Javascript 框架,对 mixin 和继承都提供了正式的支持。在SC,你可以这样做
App.MyObject = SC.Object.extend({
prop: 'prop',
func: function(){
})
Run Code Online (Sandbox Code Playgroud)
它做了你所期望的,它把prop和放在func的原型上MyObject,创建一个“类”,它可以有子类。你也可以这样做
App.MyObject = SC.Object.extend(App.OtherObject, {
// stuff
})
Run Code Online (Sandbox Code Playgroud)
它执行多重继承。然后你可以有类似的东西
CommonFunctionality = {
// some methods
};
App.mixin(CommonFunctionality);
Run Code Online (Sandbox Code Playgroud)
这会将这些CommonFunctionality内容应用到App. 如果 app 是一个命名空间(即 a {}),则 的方法CommonFunctionality将应用于该对象文字。如果有意义的话,您还可以应用于CommonFunctionality“类”,并且它的方法将位于原型上。如果你查看源代码,你会看到
SC.extend = SC.mixin ;
所以在SC中,绝对没有区别,因为它们是相同的方法。
所以细节很重要——他们本来不必这样做,但他们这样做了,而且是有影响的。如果他们采取不同的做法,那么当然会产生不同的后果。