HENRY'S BLOG

Inheritance vs Composition

Inheritance

í
In object-oriented (OO) programming, reusability of code plays a big role. Think of OO programmers as like they were smart sloths. They don't want to do much in general, and so they don't want to re-do many things. That's why the concept of objects was invented. Now, if you have a, let's say, class that provides certain functionality, you might want to provide this class with some extra functionality that someone (or even you) has done already.
The most common ways to do so are the concepts of Inheritance and composition. In the following, I will give an example of how to use them.

  1. class Parent
  2.   def override()
  3.     puts "PARENT override"
  4.   end

  5.   def implicit()
  6.     puts "PARENT implicit call"
  7.   end

  8.   def altered()
  9.     puts "PARENT altered"
  10.   end
  11. end

  12. class Child < Parent
  13.   def override()
  14.     puts "CHILD override"
  15.   end

  16.   def altered()
  17.     puts "CHILD, BEFORE PARENT altered"
  18.     super()
  19.     puts "CHILD, AFTER PARENT altered"
  20.   end
  21. end

  22. parent = Parent.new()
  23. child = Child.new()

  24. parent.implicit()
  25. child.implicit()

  26. parent.override()
  27. child.override()

  28. parent.altered()
  29. child.altered()

And this is the ouput:
  1. PARENT implicit call
  2. PARENT implicit call
  3. PARENT override
  4. CHILD override
  5. PARENT altered
  6. CHILD, BEFORE PARENT altered
  7. PARENT altered
  8. CHILD, AFTER PARENT altered
The Child class inherits from the Parent class, which means that it gets some extra functionality. There are basically three things happening here:
  1. implicit inheritance
  2. overriding an inherited method
  3. alter an inherited method
implicit means that all methods from the parent class are available to the child class. So if you call the method from the child, the parent method gets called.
overriding means that you can give a certain inherited method other functionality than the one from the parent class. This works by just defining the method in the child class with the same name as in the parent class.
alter means that you can add functionality of methods of the parent class using super(). You have to name the altered method exactly like in the parent class. You can then do whatever you want inside this method (as in overriding), but you can call the original method anytime within the altered method. For this, a simple super() calls the original method.

Composition

ì í
There are several ways of using Composition, but I'll present too options to you:
  1. Calling methods of other classes by creating an instance of a parent class in the initialization method
  2. Using modules

    1. class Child
    2.   def initialize()
    3.     @parent = Parent.new()
    4.   end

    5.   def doSomething()
    6.     @parent.doSomething()
    7.   end
    8. end

    Creating an instance of Parent lets you use any of the Parent class' methods.

    1. module Other
    2.   def doSomething
    3.     # ...
    4.   end
    5. end

    6. class Child
    7.   include Other

    8.   def doSomething_alter
    9.     # ...
    10.     Other.doSomething
    11.     # ...
    12.   end
    13. end

    Using module instead of Class let's you create a Parent/Other/Whatever pool of methods, that you can use in other (Child) classes, without the need of creating an instance of the Other class.

Conclusion

ì í
There are too many advanced aspects in this topic, so that it cannot be said in general which inheriting option you should use. module seems to be more practical than just creating instances, and also it seems to be more safe than inheriting, because you only inherit the needed methods by explicitly calling them.