This tutorial provides a comprehensive guide on using inheritance effectively in Ruby. You’ll learn how to define subclasses, use the `super` keyword to call parent class methods, and understand the concept of class hierarchies. By the end, you’ll have a solid grasp of inheritance principles and be able to apply them in real-world scenarios.
Step 1: Understanding Inheritance Basics
Inheritance allows you to define a class that inherits behavior from another class. The class that inherits is called the subclass or child class, and the class being inherited from is called the superclass or parent class.
To create a subclass, use the < symbol followed by the name of the superclass:
class ChildClass < ParentClass
# subclass definition
end
The subclass inherits all the methods and attributes from its parent class.
class Animal
def initialize(name)
@name = name
end
def speak
"Hello!"
end
end
class Dog < Animal
end
dog = Dog.new("Buddy")
puts dog.speak # Output: Hello!Practice Exercise
Create a Vehicle class with initialize, start_engine, and stop_engine methods. Then, create a Car subclass that inherits from Vehicle and adds a drive method. Instantiate a Car object and call its methods.
Show Solution
class Vehicle
def initialize(make, model)
@make = make
@model = model
end
def start_engine
puts "Engine started."
end
def stop_engine
puts "Engine stopped."
end
end
class Car < Vehicle
def drive
puts "#{@make} #{@model} is driving."
end
end
car = Car.new("Toyota", "Camry")
car.start_engine # Output: Engine started.
car.drive # Output: Toyota Camry is driving.
car.stop_engine # Output: Engine stopped.
```
In this exercise, we create a `Vehicle` superclass with basic functionality and a `Car` subclass that inherits from `Vehicle` and adds a specific `drive` method. This demonstrates the concept of inheritance and method invocation on a subclass object.Step 2: Overriding Methods in Subclasses
When a subclass defines a method with the same name as a method in its superclass, it overrides the superclass method. This allows the subclass to provide its own implementation of the method.
To override a method, simply define a method with the same name in the subclass:
class ParentClass
def greet
"Hello from ParentClass!"
end
end
class ChildClass < ParentClass
def greet
"Hello from ChildClass!"
end
end
When the greet method is called on an instance of ChildClass, the overridden version in the subclass will be executed.
class Animal
def speak
"Hello!"
end
end
class Cat < Animal
def speak
"Meow!"
end
end
cat = Cat.new
puts cat.speak # Output: Meow!Practice Exercise
Create a Shape class with a calculate_area method that raises a NotImplementedError. Then, create Rectangle and Circle subclasses that override the calculate_area method to provide their respective area calculations. Instantiate objects of each subclass and call the calculate_area method.
Show Solution
class Shape
def calculate_area
raise NotImplementedError, "Subclasses must implement the calculate_area method."
end
end
class Rectangle < Shape
def initialize(length, width)
@length = length
@width = width
end
def calculate_area
@length * @width
end
end
class Circle < Shape
def initialize(radius)
@radius = radius
end
def calculate_area
Math::PI * @radius**2
end
end
rectangle = Rectangle.new(5, 3)
puts rectangle.calculate_area # Output: 15
circle = Circle.new(4)
puts circle.calculate_area # Output: 50.26548245743669
```
In this exercise, we create a `Shape` superclass with an abstract `calculate_area` method that raises a `NotImplementedError`. The `Rectangle` and `Circle` subclasses override the `calculate_area` method to provide their specific area calculations based on their respective attributes. This demonstrates method overriding and polymorphism in action.Step 3: Using the super Keyword
The super keyword allows a subclass method to call the superclass version of the method. It is commonly used when overriding methods to extend the functionality of the superclass method rather than completely replacing it.
To call the superclass method, use super within the subclass method:
class ParentClass
def greet
"Hello from ParentClass!"
end
end
class ChildClass < ParentClass
def greet
super + " and ChildClass!"
end
end
In this example, the greet method in ChildClass calls super to invoke the greet method from ParentClass and then appends additional text to the result.
class Animal
def initialize(name)
@name = name
end
def introduce
"I am an animal."
end
end
class Dog < Animal
def introduce
super + " My name is #{@name}."
end
end
dog = Dog.new("Buddy")
puts dog.introduce # Output: I am an animal. My name is Buddy.Practice Exercise
Create an Employee class with initialize and display_info methods. The initialize method should take name and salary parameters, and the display_info method should print the employee's name and salary. Create a Manager subclass that inherits from Employee and adds a department parameter to initialize and a corresponding display_info method that calls super and appends the department information.
Show Solution
class Employee
def initialize(name, salary)
@name = name
@salary = salary
end
def display_info
"Name: #{@name}, Salary: $#{@salary}"
end
end
class Manager < Employee
def initialize(name, salary, department)
super(name, salary)
@department = department
end
def display_info
super + ", Department: #{@department}"
end
end
employee = Employee.new("John Doe", 50000)
puts employee.display_info # Output: Name: John Doe, Salary: $50000
manager = Manager.new("Jane Smith", 80000, "Sales")
puts manager.display_info # Output: Name: Jane Smith, Salary: $80000, Department: Sales
```
In this exercise, we create an `Employee` superclass with `initialize` and `display_info` methods. The `Manager` subclass inherits from `Employee` and extends the `initialize` method by calling `super` with `name` and `salary` arguments and adding a `department` parameter. The `display_info` method in `Manager` calls `super` to invoke the superclass method and appends the department information. This demonstrates the usage of `super` to extend superclass functionality in subclasses.Step 4: Class Hierarchies and Inheritance Chains
Inheritance in Ruby supports class hierarchies, where a subclass can itself serve as a superclass for other classes. This creates an inheritance chain, where methods and attributes are inherited down the hierarchy.
Here's an example of a class hierarchy:
class Animal
def speak
"Hello!"
end
end
class Mammal < Animal
def feed_young
"Feeding young..."
end
end
class Dog < Mammal
def fetch
"Fetching..."
end
end
In this hierarchy, Animal is the superclass of Mammal, and Mammal is the superclass of Dog. The Dog class inherits methods from both Mammal and Animal.
class Animal
def speak
"Hello!"
end
end
class Mammal < Animal
def feed_young
"Feeding young..."
end
end
class Dog < Mammal
def fetch
"Fetching..."
end
end
dog = Dog.new
puts dog.speak # Output: Hello!
puts dog.feed_young # Output: Feeding young...
puts dog.fetch # Output: Fetching...Practice Exercise
Create a class hierarchy for a library system. Start with a Publication class that has title and publisher attributes and a display_info method. Create a Book subclass that inherits from Publication and adds author and isbn attributes. Create a Magazine subclass that inherits from Publication and adds issue_number and publication_date attributes. Override the display_info method in both subclasses to include the additional attributes.
Show Solution
class Publication
def initialize(title, publisher)
@title = title
@publisher = publisher
end
def display_info
"Title: #{@title}, Publisher: #{@publisher}"
end
end
class Book < Publication
def initialize(title, publisher, author, isbn)
super(title, publisher)
@author = author
@isbn = isbn
end
def display_info
super + ", Author: #{@author}, ISBN: #{@isbn}"
end
end
class Magazine < Publication
def initialize(title, publisher, issue_number, publication_date)
super(title, publisher)
@issue_number = issue_number
@publication_date = publication_date
end
def display_info
super + ", Issue Number: #{@issue_number}, Publication Date: #{@publication_date}"
end
end
book = Book.new("Ruby Programming", "ABC Publishers", "John Smith", "978-1234567890")
puts book.display_info
# Output: Title: Ruby Programming, Publisher: ABC Publishers, Author: John Smith, ISBN: 978-1234567890
magazine = Magazine.new("Tech Monthly", "XYZ Media", 42, "May 2023")
puts magazine.display_info
# Output: Title: Tech Monthly, Publisher: XYZ Media, Issue Number: 42, Publication Date: May 2023
```
In this exercise, we create a class hierarchy for a library system. The `Publication` class serves as the superclass, with `Book` and `Magazine` as subclasses. Each subclass adds its specific attributes and overrides the `display_info` method to include the additional information. This demonstrates the concept of class hierarchies and method overriding in a practical scenario.Step 5: Accessing Superclass Methods with super()
When using super without parentheses, Ruby automatically passes all arguments from the subclass method to the superclass method. However, you can also explicitly pass arguments to the superclass method using super().
Here's an example:
class ParentClass
def greet(name)
"Hello, #{name}!"
end
end
class ChildClass < ParentClass
def greet(name)
super(name.upcase)
end
end
In this case, the greet method in ChildClass calls super(name.upcase), passing the modified name argument to the superclass method.
class Animal
def make_sound(sound)
"#{sound}!"
end
end
class Cat < Animal
def make_sound(sound)
super("Meow")
end
end
cat = Cat.new
puts cat.make_sound("Purr") # Output: Meow!Practice Exercise
Create a Person class with an initialize method that takes name and age parameters and a display_info method that prints the person's name and age. Create a Student subclass that inherits from Person and adds a grade parameter to initialize. Override the display_info method in Student to call the superclass method using super() and append the grade information.
Show Solution
class Person
def initialize(name, age)
@name = name
@age = age
end
def display_info
"Name: #{@name}, Age: #{@age}"
end
end
class Student < Person
def initialize(name, age, grade)
super(name, age)
@grade = grade
end
def display_info
super() + ", Grade: #{@grade}"
end
end
person = Person.new("John Doe", 30)
puts person.display_info # Output: Name: John Doe, Age: 30
student = Student.new("Jane Smith", 18, 12)
puts student.display_info # Output: Name: Jane Smith, Age: 18, Grade: 12
```
In this exercise, we create a `Person` class with `initialize` and `display_info` methods. The `Student` subclass inherits from `Person` and adds a `grade` parameter to `initialize`. In the `Student` class, the `display_info` method calls `super()` to invoke the superclass method and appends the grade information. This demonstrates the usage of `super()` to pass arguments explicitly to the superclass method.Sign in to take Cornell notes on this lesson — they save automatically and stay with your account.