为什么使用对象继承而不是 mixin
相比 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 一样,类关系将被视为一个平面列表。
假设我们使用的语言
- 允许使用非详细语法进行混合,
- 这允许我们透明地将
FullTimeEmployee
视为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)
//
What are the reasons to favour inheritance over mixins
Given the following psuedo-code example :
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
If we were to use inheritance to build objects the class relations would be seen as a tree where as with mixins the class relations would be seen as a flat list.
Assuming the language we are using
- allows for mixins with a non-verbose syntax
- allows us to treat
FullTimeEmployee
as both aEmployee
andFullTime
object transparently.
why should we build up our class relations as trees (inheritance) instead of flat lists (composition)?
Example of tree versus list.
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)
//
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为,在支持 mixins 的语言中,它实际上与使用(多重)继承相同。在这两种情况下,相关的类/对象上存在相同的方法/属性,两者的调用方式完全相同——没有实际区别。我还假设在这种假设的语言中,您也可以从多个“类”进行“扩展”。
如果这一切都是真的,那么在某种程度上它们是等效的,并且这个问题没有意义——没有一个比另一个更好,因为它们在功能上是等效的。
从人类理解的角度来看,我认为大多数人都认为继承是 isA 关系,混合是用功能来装饰某些东西。
如果您只能从一个“类”继承,那么显然 mixins 是一种获得多重继承的方法。
编辑——根据你的评论,这些评论很好,我想说假设语言的细节很重要。我承认我的答案是基于 Sproutcore,它是一个 Javascript 框架,对 mixin 和继承都提供了正式的支持。在 SC 中,您可以执行
您所期望的操作,它将
prop
和func
放在MyObject
的原型上,创建一个“类” ,它可以有子类。您还可以执行多重继承。然后,您可以拥有类似的东西
,将
CommonFunctionality
内容应用于App
。如果应用是一个命名空间(即{}
),则CommonFunctionality
的方法将应用于该对象字面量。如果有意义的话,您还可以将 CommonFunctionality 应用于“类”,并且其方法将位于原型上。如果你查看源代码,你会看到SC.extend = SC.mixin ;
所以在 SC 中,绝对没有区别,因为它们是相同的方法。
所以细节很重要——他们本来不必这样做,但他们这样做了,而且是有影响的。如果他们采取不同的做法,那么当然会产生不同的后果。
I would argue that in languages that do support mixins, it is effectively the same as using (multiple) inheritance. In both cases, the same methods/properties exist on the class/object in question, both are invoked the exact same way -- there is no practical distinction. I'm also assuming that in this hypothetical language, you can 'extend' from multiple 'classes' as well.
If this is all true, then in a way they are equivalent and the question doesn't make sense - neither is better than the other because they are functionality equivalent.
In a human-understanding sort of way, I think most people think of inheritance in terms of the
isA
relationship, and mixins in terms of decorating something with functionality.If you can only inherit from one 'class', then obviously mixins are a way to sort of gain multiple inheritance.
EDIT -- based on your comments, which are good, I would say the details of the hypothetical language matter. I will admit I am basing my answer of the Sproutcore, which is a Javascript framework that has formalized support for both mixins and inheritance. In SC, you can do
which does what you would expect, it puts
prop
andfunc
on the prototype ofMyObject
, creating a "class", which could have subclasses. You could also dowhich does multiple inheritance. You could then have something like
which would apply the
CommonFunctionality
stuff toApp
. If app was a namespace (i.e. a{}
) the methods ofCommonFunctionality
would be applied to that object literal. If it made sense, you could also applyCommonFunctionality
to a "class", and its methods would be on the prototype. If you look in the source, you seeSC.extend = SC.mixin ;
So in SC, there is absolutely no difference because they are the same method.
So details matter -- they didn't have to do it that way, but they did, and there are implications. If they had done it differently, then of course there would be different consequences.
当有必要时你应该使用。如果您有一个包含 1000 行的大类,并且您发现自己在多个类中重复相同的内容,则可以将一些逻辑封装在基类中,将其他逻辑封装在 mixin 中。每个mixin都有有限的上下文,他们可能知道的比他们应该知道的多,但他们只专注于某个任务。因此非常模块化。
好吧,我可以给你的最好的例子是一个游戏的 Actor具有一些基本内容的继承,但使用 mixins/用于共享功能的插件。共享功能可以是(直接来自源代码!):
这最初是一个包含 +1000 行的类。
You should use when the necessity appears. If you have a big class with 1000 lines and you are finding yourself repeating the same stuff across multiple classes you can encapsulate some logic in a base class and other in mixins. Each mixin has a limited context, they might be aware about more than they should, but they only focus on a certain task. Therefore are very modular.
Well, the best example I can give it to you is an Actor for a game which has inheritance for some base stuff but uses mixins/plugins for shared functionality. The shared functionality could be (directly from the source code!):
This originally was a class with +1000 lines.
在设计时,我们尝试尽可能模拟现实。
考虑到
is a
和has a
原则,FullTimeEmployee 是具有附加(额外)功能的员工
,并且不是除了所谓的FullTime
之外还有员工
的新事物,以及PartTimeEmployee
依此类推。When designing we try to simulate reality as much as we can.
Considering the
is a
and thehas a
principles, aFullTimeEmployee is an Employee
who has additional (extra) feature, and not some new thing thathas an Employee
beside something calledFullTime
, and so on for thePartTimeEmployee
.