# Explain Polymorphism in OOPs.
Polymorphism is a core concept in Object-Oriented Programming (OOP) that allows objects of different classes to be treated as objects of a common super class. It provides a way to use a single interface to represent different data types. In Ruby, polymorphism can be achieved in several ways, such as through inheritance, method overriding, and duck typing.
1. Inheritance and Method Overriding
Inheritance allows a class to inherit methods and attributes from another class. Method overriding is when a subclass provides a specific implementation of a method that is already defined in its superclass.
class Animal
def speak
puts "Animal speaks"
end
end
class Dog < Animal
def speak
puts "Woof!"
end
end
class Cat < Animal
def speak
puts "Meow!"
end
end
# Polymorphism in action
animals = [Dog.new, Cat.new]
animals.each do |animal|
animal.speak
end
# Output:
# Woof!
# Meow!In this example, the `speak` method is defined in the `Animal` class and overridden in both the `Dog` and `Cat` classes. When the `speak` method is called on objects of these subclasses, the respective overridden method is executed.
2. Duck Typing
Duck typing in Ruby is a way to achieve polymorphism without relying on a class hierarchy. It is based on the principle: "If it looks like a duck and quacks like a duck, it is a duck." This means that if an object responds to the methods that are expected of it, it can be used in place of any other object that has the same methods.
class Duck
def quack
puts "Quack!"
end
end
class Person
def quack
puts "I'm quacking like a duck!"
end
end
# Polymorphism in action
def make_it_quack(duck)
duck.quack
end
make_it_quack(Duck.new) # Output: Quack!
make_it_quack(Person.new) # Output: I'm quacking like a duck!In this example, both `Duck` and `Person` classes have a `quack` method. The `make_it_quack` method can accept an instance of either class and call the `quack` method, demonstrating polymorphism through duck typing.
Summary
Polymorphism in Ruby allows for flexibility and reuse of code by enabling objects of different types to be treated uniformly based on common methods they implement. This is achieved through inheritance and method overriding or duck typing, providing a way to design more abstract and generalized code.