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
FullTimeEmployee
as both a Employee
and FullTime
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)
//
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
App.MyObject = SC.Object.extend({
prop: 'prop',
func: function(){
})
which does what you would expect, it puts prop
and func
on the prototype of MyObject
, creating a "class", which could have subclasses. You could also do
App.MyObject = SC.Object.extend(App.OtherObject, {
// stuff
})
which does multiple inheritance. You could then have something like
CommonFunctionality = {
// some methods
};
App.mixin(CommonFunctionality);
which would apply the CommonFunctionality
stuff to App
. If app was a namespace (ie a {}
) the methods of CommonFunctionality
would be applied to that object literal. If it made sense, you could also apply CommonFunctionality
to a "class", and its methods would be on the prototype. If you look in the source, you see
SC.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.
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!):
var plugins = {
SingleVisualEntity : SingleVisualEntity,
JumpBehaviour : JumpBehaviour,
WeaponBehaviour : WeaponBehaviour,
RadarBehaviour : RadarBehaviour,
EnergyGatherer : EnergyGatherer,
LifeBarPlugin : LifeBarPlugin,
SelectionPlugin : SelectionPlugin,
UpgradePlugin : UpgradePlugin,
BrainPlugin : BrainPlugin,
PlanetObjectPlugin : PlanetObjectPlugin,
}
This originally was a class with +1000 lines.
When designing we try to simulate reality as much as we can.
Considering the is a
and the has a
principles, a FullTimeEmployee is an Employee
who has additional (extra) feature, and not some new thing that has an Employee
beside something called FullTime
, and so on for the PartTimeEmployee
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.