5

gist

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 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)
//
Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145
Raynos
  • 166,823
  • 56
  • 351
  • 396
  • Would you consider this a duplicate of [Why use inheritance at all?](http://stackoverflow.com/questions/3351666/why-use-inheritance-at-all) ? – daxelrod Sep 16 '11 at 23:42
  • 1
    @daxelrod no because that's comparing inheritance to delegation and it also doesn't answer my question. My question is mainly about building class relations as trees versus flat lists. – Raynos Sep 16 '11 at 23:49
  • What are FullTime and PartTime when they're not associated with Employee? – Terry Wilcox Sep 17 '11 at 00:15
  • @TerryWilcox I believe loose coupling of `FullTime` from `Employee` is a habit of over engineering on my part – Raynos Sep 17 '11 at 00:26
  • Then I think you've answered your own question. Prefer composition over inheritance, but use inheritance when it makes sense. FullTimeEmployee makes more sense as a subclass of Employee than it does as an Employee with a FullTime. – Terry Wilcox Sep 17 '11 at 00:41
  • @TerryWilcox the question is "when does it make sense". Why does it make more sense as a subclass then an Employee with FullTime. Does changing the wording to "WorksFullTime" make combining "Employee" and "WorksFullTime" more reasonable? – Raynos Sep 17 '11 at 00:44
  • @Raynos Neither FullTime nor WorksFullTime make sense as objects. An Employee doesn't have a WorksFullTime and a WorksFullTime is a what? Would you ever use it in the absence of an Employee? I'd prefer Inheritance over bad design in the name of Composition. – Terry Wilcox Sep 17 '11 at 01:17
  • @TerryWilcox a WorksFullTime is an object that implements methods to do with working full time. And it should read as FullTimeEmployee is a union of WorksFullTime and Employee. You may be confusing composition with mixins. I should change all references to composition to mixin. Once again the loose coupling of WorksFullTime from Employee may be overengineering or it's a simple case of a bad example. – Raynos Sep 17 '11 at 01:20

3 Answers3

3

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 (i.e. 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.

hvgotcodes
  • 118,147
  • 33
  • 203
  • 236
  • The main difference is chaining. Why would you set up an inheritance chain/tree when you can just have a flat list or linked list. – Raynos Sep 16 '11 at 23:53
  • Also how are mixins different from classical inheritance in popular implementations? Am I confusing how mixins work? – Raynos Sep 16 '11 at 23:56
  • [I already know the value of inheritance & composition in JS](http://stackoverflow.com/questions/7294276/why-use-chained-prototype-inheritance-in-javascript) but that's prototypical inheritance instead of classical inheritance. Which is a different ball game. Also in SC `extend` is not inheritance. It's just another name for `mixin`. – Raynos Sep 17 '11 at 00:56
  • 1
    right, but extend adds the stuff in the argument to the prototype, so its creating a 'class'. class in quotes, because of the prototypical inheritance. That's my point, there is little difference between 'mixing something in' and 'extending' – hvgotcodes Sep 17 '11 at 01:08
  • links to source. Again the main difference is that extension is a live link, where as mixed in objects are static shallow clones. – Raynos Sep 17 '11 at 01:10
0

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.

Totty.js
  • 15,563
  • 31
  • 103
  • 175
-1

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.

Tamer Shlash
  • 9,314
  • 5
  • 44
  • 82
  • 1
    mixins are not `has an`. If `FullTimeEmployee` had a field named `Employee` then that's a `has an` relation. – Raynos Sep 17 '11 at 00:00
  • @Raynos: If `FullTimeEmployee` had a field named `Employee` then logically he would no longer be an `Employee`, but something that `has a` or includes an `Employee`. another Example is that a `Taxi` is a `car` that has some specifiactions, we can't say that a `Taxi has a car`, that is not reasonable. – Tamer Shlash Sep 17 '11 at 00:13