Object-Oriented Programming in Ruby. Basics and definitions (2/2)

Faouzi
Faouzi
Jun 18 · 11 min read
Classes and Modules in Ruby
  • What are the possible relations between classes? between objects?
  • How can we capitalize on the commonalities that may exist between various classes?

Inheritance and its implementation.

Looking at the definition for ‘inheritance’ that we get from the dictionary, already gives us some keys notions:

  • What we receive can alter the way we look and behave (notion of cultural or genetic inheritance).
How to implement Inheritance in Ruby
A more elaborated inheritance example. Sub-classing produces a hierarchical tree with more specialized classes.
  • Car being a subclass of Vehicle , its instance responds to method calls from its own class but also from the Vehicle class (line 42–47). As saw in our first example.
  • Now comes the interesting part. FlyingCar is a subclass of Car . This means that FlyingCar inherits from Car but also from Vehicle. Indeed our instance flyingcar answers to method calls defined in Vehicle and Car classes. This illustrated very well how inheritance in Ruby can progressively create a hierarchical tree with extended and more specialized sub-classes.
  • In Ruby we can easily visualize this hierarchical tree. In line 57 we call the class method ancestors on the FlyingCar class. The return value of this method called lists in an Array the corresponding hierarchical tree. In Ruby the ancestors class method is commonly used to check the method lookup path (Launch school). By definition, to resolve a method call on an object, Ruby will look for the expected method going through the class hierarchy.

Modules in Ruby: a tool to circumvent the lack of multiple inheritance.

We said it earlier. Ruby does not implement multiple inheritance. Instead we can only subclass one class from one super-class. This is a drastic choice but avoid to fall into ambiguous class design. Have a look to this code:

  • They are classically used to extract common methods / behaviors that map has-a relationships between classes. It allows to provide common functionality to objects from different classes. In our case humans has the ability to swim, so do fishes. we could then extract this method into a module and get the following code:

Polymorphism.

Let’s do the same exercise as previously. Here a proposed definition of polymorphism:

Inheritance Polymorphism.

To answer this question let’s think about it. Our classes are designed to produce objects (that encapsulate data and behaviors) and give us the mean to manipulate them. To manipulate them we need interfaces / methods. Objects can answer to specific method calls which result in specific behaviors. We just saw that with inheritance we could share common methods between classes. In our previous example, objects instantiated from Car and FlyingCar classes share the instance method energy and respond to its call similarly meaning that they exhibit a common behavior. But let’s imagine now that our flying cars can use solar energy and oil to function. We would need here to modify the implementation of the method energy. Let’s do it:

Method Overriding

Using super.

Before diving into another type of polymorphism. We will talk a little bit about the built-in function provided by Ruby and called super . It allows us to call methods up the inheritance hierarchy tree. When calling super from inside a method, it will search in the method lookup path for a method with the same name and then invoke it. super will then return the value of this method and can be used to implement inheritance polymorphism.

Using super for method overriding

Interface Polymorphism.

In their book Hal Fulton and Andre Arko report a definition of polymorphism proposed by Damian Conway and translate it to Ruby (Fulton and Arko 2015). They define a second type of polymorphism called interface polymorphism. This does not require any inheritance relationship between classes but essentially the definition of methods with similar names. This touches a point that is very important in Ruby: the importance of messages. Objects receive messages or “answer” to method calls. Ruby does not care about the type of the object as long as it can receives and interprets the message. A very clear example of this is Duck Typing:

Before Duck-Typing…
After Duck Typing

Modules and interface polymorphism

Another way of implementing interface polymorphism would be to combine modules with method overriding. Modules would provide common interfaces to several different classes’ instances when method overriding could be a way to re-write and modify methods to provide more specific functionalities only in some of your classes. While possible this is not the way modules are usually used in Ruby (Fulton and Arko 2015). Indeed modules are considered to be part of the class they are mix-in, this process being viewed as providing some level of multiple inheritance (Fulton and Arko 2015) as discussed previously.


Conclusion

This article aims at defining two critical concepts of OOP: Inheritance and Polymorphism. As a conclusion and for the laziest readers, here are some straightforward definitions for these concepts (adapted from Damian Conway 1999):

  • Polymorphism: Ability for different objects, instantiated from different classes to respond in different ways to the SAME message / interface / method calls
  • Inheritance Polymorphism: A form of polymorphism that requires an invoking object to belong to a particular class hierarchy. Under inheritance polymorphism, a method can only be invoked on an object if the object belongs to the hierarchical tree, up to the original super-class (Implementation by method overriding or using super).
  • Interface Polymorphism: A form of polymorphism that does not require the invoking object to belong to a particular class hierarchy. Under interface polymorphism, a method may be invoked on an object if the object’s class has a suitably named method (Implementation using Duck Typing, possibility to implement it using modules + method overriding)

Bibliography (in order of citation)

  1. An Introduction to Object-Oriented Programming (3rd Edition). Timothy A Budd. Addisson Wesley Longman. ISBN 0–201–76031–2. 2002. Free chapter samples here.
  2. Object Oriented Programming with Ruby. Launch School. Available online (https://launchschool.com/books/oo_ruby).
  3. Object Oriented Perl. Damian Conway. Manning. ISBN 9781884777790. 1999.
  4. The Ruby Way: Solutions and Techniques in Ruby Programming (3rd Edition). Hal Fulton and Andre Arko. Addison-Wesley Professional Ruby Series. ISBN-13: 978–0321714633. 2015.

Launch School

Publications of the Launch School Community

Faouzi

Written by

Faouzi

Launch School

Publications of the Launch School Community