Inheritance in Ruby
Ruby supports the core idea of inheritance in object-oriented programming, which enables the construction of new classes based on preexisting ones, encouraging code reuse and constructing hierarchies. Inheritance in Ruby is a core object-oriented programming concept that allows a class to inherit properties and behaviors (methods) from another class. This promotes code reusability and helps in establishing a hierarchical relationship between classes.
Fundamentals of Inheritance
Based on an existing class, inheritance enables a class to define particular behavior.
Subclass and Superclass: If a new class is formed based on an existing one, it is termed a subclass (also known as a child class or descendent), and the superclass (also known as a parent class or base class) is the existing class from which it inherits its behavior.
Syntax: Between the class name and the superclass name, the < character is used to define inheritance:
Single Inheritance: There can only be one immediate superclass for a class in Ruby due to single inheritance support. The base class Object is implicitly extended by the class if no superclass is defined.
Class Hierarchy: Object is the root of the Ruby class hierarchy, which is a tree structure that organizes classes.
What is Inherited?
A class can access different elements defined by the parent when it inherits from a superclass:
Instance Methods: The subclass inherits the methods of the superclass.
Class Methods: Inheritable are also methods that are defined as class methods (def self.method).
Constants: The subclass has access to and the ability to override constants defined in the superclass.
Private Methods: Subclasses can invoke and override private methods, which they inherit.
Key Mechanisms: Overriding and Chaining ()
Overriding or augmenting methods defined in the parent class is a potent feature of inheritance.
Overriding Methods: The inherited behavior can be modified by a subclass by redefining a method with the same name. This is dependent on method name resolution, in which Ruby dynamically retrieves the relevant method definition during execution.
Method Chaining with super: The super keyword is used when you wish to override a method while retaining the original logic from the superclass. Without completely altering the parent’s behavior, the subclass can enhance or embellish it by using super. Using this approach is very typical when working with the initialize method.
Code Example: Basic Inheritance and Overriding
This example demonstrates how overriding and method inheritance operate:
class Animal
def say_hello
'Meep!'
end
def eat
'Yumm!'
end
end
class Dog < Animal
def say_hello
'Woof!'
end
end
spot = Dog.new
puts spot.say_hello # 'Woof!'
puts spot.eat # 'Yumm!'
Output
Woof!
Yumm!
This idea makes it possible to reuse code. For example, if two classes have the same method, it may be transferred to a common Animal superclass, which will remove unnecessary code.
Code Example: Chaining with initialize
To guarantee that the parent class is initialized appropriately, or when a method is supplemented, the super keyword is usually used in the initialize method:
class A
def initialize(p1)
puts "Initializing A: p1 = #{p1}"
@var1 = p1 # Superclass instance variable is set here
end
end
class B < A
attr_reader :var1, :var2
def initialize(p1, p2)
# Pass our first argument along to the superclass initialize method
super(p1)
# And deal with the second argument ourself
puts "Initializing B: p2 = #{p2}"
@var2 = p2
end
end
b = B.new("cat", "dog")
puts b.inspect
Output
Initializing A: p1 = cat
Initializing B: p2 = dog
#<B:0x000079319e7b3420 @var1="cat", @var2="dog">
A subclass may leave instance variables from the superclass at zero if it overrides an initialize method without contacting super.
Variable Behavior
In Ruby, variables can exhibit complicated behavior in an inheritance hierarchy:
Instance Variables (@variable): It is not inherited to use instance variables. The instant a value is assigned to an object, they are generated on that object. The fact that they are typically assigned values by methods (like initialize) that are either inherited or chained using super gives the impression that they are inherited.
Class Variables (@@variable): Every class and all of its subclasses share the same class variables. Because just one copy is shared, whenever a child class changes a value in a class variable, it also changes the value for the parent class and all its descendants. Programmers frequently employ class instance variables as a result of this feature.
Class Instance Variables (e.g., @foo defined outside instance methods): Subclasses are not inheritable of these variables, which are linked to the class object itself.
Simulating Multiple Inheritance (Mixins)
Ruby does not support multiple inheritance in the conventional sense. Instead, it adds bundles of methods to a class using Modules as Mixins. The power of multiple inheritance is combined with the simplicity of unclear hierarchies in this compromise.
Both instance methods (including) and class methods (extend) can be used to include the module’s methods. An ancestor of the class is created when a module is added.
Code Example: Mixins
module Foo
def foo_method
puts 'foo_method called!'
end
end
module Bar
def bar_method
puts 'bar_method called!'
end
end
class Baz
include Foo # Mixes in Foo's methods
include Bar # Mixes in Bar's methods
def baz_method
puts 'baz_method called!'
end
end
new_baz = Baz.new
new_baz.baz_method #=> 'baz_method called!'
new_baz.bar_method #=> 'bar_method called!'
new_baz.foo_method #=> 'foo_method called!'
Output
baz_method called!
bar_method called!
foo_method called!
You can also read What Is The Command Line Crash Course Manipulation in Ruby