Picture of myself

Inheritance, Composition, Mixins

January the 31st in year 2015

When we start our programming life, our code is very short, but sooner or later there comes a time when we realise it has become too long. This is the time when we need to make a decision how are we going to split our code in to smaller objects. And there are three ways of doing that:

With inheritance
With composition
With mixins

Inheritance:

I'll make an example about life. One common thing all living things have is that they reproduce. So we'll make life our superclass. All living things inherit that property of life. So if we make a class Animal, we can have it inherit all the methods life has. All we need to do is tell the computer that Animal class is less than Life class (Animal < Life) when we declare it.

  class Life
    def reproduction
      puts "Let's make more of us"
    end
  end

  class Plant < Life
    def photosynthesis
      puts "Let's use some carbon dioxide"
    end
  end

  class Animal < Life
    def move
      puts "Let's go somewhere"
    end
  end

  plant_object = Plant.new
  plant_object.reproduction
  plant_object.photosynthesis

  animal_object = Animal.new
  animal_object.reproduction
  animal_object.move

And our output is:

=> Let's make more of us
=> Let's use some carbon dioxide
=> Let's make more of us
=> Let's go somewhere

And so it works. It's that simple.
Downside of inheritance is that subclasses get all the methods from superclass, and so do all the subclasses of subclass and so on. This can cause massive headaches when applications are big.

So what we can do is, we can get only method we need from a separate class and put it in our own.

Composition:

When we use composition we create an instance of another class within our own class to get the method we want. In this case we can control what methods we get from other class, and we can get them from more than one, not like with inheritance where we can only pick one superclass and then we get everything with it, including the rubbish we don't need. So let's see how it's done.

  class Life
    def reproduction
      puts "Let's make more of us"
    end
  end

  class Plant
    def seed
      life_object = Life.new
      life_object.reproduction
    end
    def photosynthesis
      puts "Let's use some carbon dioxide"
    end
  end

  class Animal
    def mate
      life_object = Life.new
      life_object.reproduction
    end
    def move
      puts "Let's go somewhere"
    end
  end

  plant_object = Plant.new
  plant_object.seed
  plant_object.photosynthesis

  animal_object = Animal.new
  animal_object.mate
  animal_object.move

=> Let's make more of us
=> Let's use some carbon dioxide
=> Let's make more of us
=> Let's go somewhere

And we get the same result. Notice that we created a new method in Animal class called 'mate', so this is what we are then calling, and it is than the mate method that in turn calls the method reproduction. This is very useful if we only need a small piece of other class, like one method that we could use in ours.

But if we want more than one method and we want to apply it to multiple classes we can use something called modules.

Mixins:

Modules are just like classes but different. I'm not going to go deep into differences between the two, but what's important for us to know now is that we can't make an instance of a module. What we do with them is to include them in our classes, with the magic word, yes you guessed it include. If we do that, then all of the methods in the module are available in the class. Like here in our example, reproduction is available in Plant class because we said include Life.

  module Life
    def reproduction
      puts "Let's make more of us"
    end
  end

  class Plant
    include Life
    def photosynthesis
      puts "Let's use some carbon dioxide"
    end
  end

  class Animal
    include Life
    def move
      puts "Let's go somewhere"
    end
  end

  plant_object = Plant.new
  plant_object.reproduction
  plant_object.photosynthesis

  animal_object = Animal.new
  animal_object.reproduction
  animal_object.move

=> Let's make more of us
=> Let's use some carbon dioxide
=> Let's make more of us
=> Let's go somewhere

If we were to add another method in module Life, like for example has_cells, than all of the classes were we included Life, would have gained the method. Imagine you need to create a class Cat. You could simply include the module in it and that would be it. The best thing about mixins is that you can include as many modules as you want, even though it's not the best idea to have countless modules added, but anyway, you can do it. Compared to inheritance, where you're limited to one class to inherit from, this gives you more options.

On the bottom line, mixins seem to be the way of choice in ruby world, and inheritance seems to be quite the opposite, but like everything else in the world, it all comes down to personal opinion. Use whatever suits you, but be aware of the what your choice gives and takes.

...by Marko Anton Potocnik