Basic Polymorphism
In Ruby, inheritance polymorphism can be achieved doing something like the following:class Bird def initialize(name) @name = name end def speak puts 'Tweet' end def fly puts 'Up up and away...' end endThis is our base class, Bird. All other classes will inherit the methods in this class.
class Duck < Bird def speak puts "Quack I am #{@name}" end end class Penguin < Bird def speak puts "Squak I am #{@name}" end def fly puts 'Nope. I swim...' end endThese are the classes that inherit from our base class. Ducks and Penguins are Birds. So, they will have basic methods speak() and fly(). The cool thing is we can override existing methods of the superclass from within the subclass to change the default behavior of a Bird. For example, Penguins don't tweet or fly. So, we override the base methods to better reflect the behavior of penguins.
So, now we can do something like this:
birds = [Bird.new('Tweetie'), Duck.new('Donald'), Penguin.new('Mumbo')] birds.each do |b| b.fly end # Up up and away... # Up up and away... # Nope. I swim... birds.each do |b| b.speak end # Tweet # Quack I am Donald # Squak I am Mumbo
The Ruby Way
In Ruby, traditional methods of polymorphism (seen above and in languages such as Java) are not widely accepted. A concept known as "duck typing" is preferred. You can read more about duck typing here.Basically, we follow a simple rule: If it walks, swims, and quacks like a duck, I call that bird a duck
We can get the same type of "polymorphic" behavior by simply implementing each method individually in each class and including any common methods:
class Duck def speak puts "Quack I am #{@name}" end def fly puts 'Up up and away...' end end class Penguin def speak puts "Squak I am #{@name}" end def fly puts 'Nope. I swim...' end endNow, each type of Bird has its methods individually defined according to its own specific behavior. What about the shared initialize() constructor?
module Bird def initialize(name) @name = name end endWe put any shared methods in a module. This way, we can include them in our classes:
class Duck include Bird ... end class Penguin include Bird ... end
Do It Your Way
I have no strong opinion on whatever approach you decide to use. There are evangelists on both ends who live and die by either one. Solve your problem any way you please!Resources:
Ruby polymorphism discussion: http://stackoverflow.com/questions/137661/how-do-you-do-polymorphism-in-ruby
The Ruby Way excerpt: http://books.google.com/books?id=ows9jTsyaaEC&pg=PA14
Ruby Learning: http://rubylearning.com/satishtalim/ruby_inheritance.html
Very nice, thank you. Is duck typing intended to fully replace inheritance, or are there some cases where inheritance is preferred, even in ruby?
ReplyDelete