Intro to Inheritance in Ruby
What is inheritance?
That’s when your mom, dad, grandma, second uncle, or great aunt once removed passes something on to you, right? Well, umm… Yes!
Inheritance in Ruby is when one class inherits behavior from another class.
Inheritance is a relationship between two classes. The smaller class (called a sub-class) inherits behavior from the larger class (called a super-class).
We can think of this as a hierarchy:
We know that both a Hero
and an Adult
are Human
, so we infer that they share some common behaviors.
class Human
def get_dressed
puts "putting on my shoes”
end def run
puts “I’m running!"
end
endclass Hero < Human
endclass Adult < Human
enddash = Hero.new
george = Human.newdash.run # => “I’m running!”
george.get_dressed # => “putting on my shoes”
In Ruby, we use the <
symbol to show inheritance. In the above example, the class Hero
inherits methods from the class Human
. This means that all methods available to a Human
are now shared with a Hero
. Likewise, those same methods available to a Human
are also inherited by the Adult
class.
Why use inheritance?
Inheritance helps us create and maintain DRY code. We can remove repetitious code from our program and source it to one, easy to trace place.
That means if we need to make a change to multiple classes that share similar structure and behavior — we can just make one change to our code!
Method Overriding
Imagine a time when a class should not inherit the exact same functionality. If we take our example, our Hero
class will probably #get_dressed
differently than our Human
class. We can override a method by defining it within our sub-class. Ruby will first check for a method in the class it is in, then follow the hierarchy to check for a method in the super-class.
class Hero < Human
def get_dressed
puts “Where is my super suit?"
end
end
Super
Super is another way to specialize and refine a class with inheritance. When super
is called within a method, it searches for a method with the same name in the inheritance hierarchy.
class Hero < Human
def run
super + “Really, really fast!!!”
end
enddash = Hero.new
dash.run # => “I’m running! Really, really fast!!!”
In the example, super finds the method in the super-class and puts “I’m running!”
To refine our run
method, we can interpolate another string, appending the text “Really, really fast!!!”
to the result.
Super & #Initialize
A pair literally made for each other. A common use of super is in the initialize method.
class Human
attr_reader :name
def initialize(name)
@name = name
end
endclass Hero < Human
def initialize(power)
super
@power = power
end
endsplash = Hero.new("water-breathing")
Now, we might assume that splash is now assigned a power of breathing underwater. However, super has some arguments of its own. Super expects to take in a name and instead of @power="water-breathing"
we have @name="water-breathing”
Huh? Let’s try again.
class Hero < Human
def initialize(name, power)
super(name)
@power = power
end
endsplash = Hero.new("Splash", "water-breathing")
That’s better! Now the arguments match what we expected. Super calls up the method look-up chain and assigns name based on the inherited #initialize
method.
Want to learn more about class relationships? Check out modules and namespacing!