Table of contentsClick link to navigate to the desired location
This content has been automatically translated from Ukrainian.
In Ruby, as in many other object-oriented languages, inheritance is a mechanism by which a class can inherit properties and methods from another class. The class that inherits is called a subclass, and the class from which it inherits is called the superclass.
Example of Bad Inheritance in Ruby
class Animal
def speak
puts "Animal speaks"
end
end
class Dog < Animal
def speak
puts "Dog barks"
end
end
class Cat < Animal
# This class does not define its own speak method
end
In this example, the Dog class inherits from the Animal class, but the Cat class does not provide its own implementation of the speak method. If you try to create an instance of the Cat class and call the speak method, it will use the implementation from the Animal class. This can be problematic, as the appropriate response for a cat is meow.
That is, we expect to get the text 'Cat meows', but we get 'Animal speaks'. It may seem not very critical, but in classes responsible for business logic, this can lead to bigger problems.
We can do the following:
class Cat < Animal
def speak
puts "Cat meows"
end
end
This seems to solve the problem. But imagine there are dozens or hundreds of classes and methods. This approach is not a best practice.
Example of Good Inheritance in Ruby
class Shape
def initialize(color)
@color = color
end
def draw
puts "Drawing a #{@color} shape"
end
end
class Circle < Shape
def initialize(color, radius)
super(color)
@radius = radius
end
def draw
puts "Drawing a #{@color} circle with radius #{@radius}"
end
end
class Square < Shape
def initialize(color, side_length)
super(color)
@side_length = side_length
end
def draw
puts "Drawing a #{@color} square with side length #{@side_length}"
end
end
In this example, there is a Shape class, which is the base class for all geometric figures. The class has a color attribute and a draw method that outputs a drawing message.
The Circle and Square classes inherit from the Shape class and provide their own attributes (radius and side_length) and implementation of the draw method. Each class can call the draw method, but with its own context and data.
This approach allows for creating common properties and methods in the base class, and then extending them in subclasses, providing their own unique logic. This makes the code more readable, maintainable, and flexible.
This post doesn't have any additions from the author yet.