Duck Typing
You'll have noticed that in Ruby we don't declare the types of variables or methods - everything is just some kind of object. Ruby objects (unlike objects in some other object-oriented languages) can be individually modified. You can always add methods on a per object basis. In Ruby, the behavior or capabilities of an object can deviate from those supplied by its class.
In Ruby, we rely less on the type (or class) of an object and more on its capabilities. Hence, Duck Typing means an object type is defined by what it can do, not by what it is. Duck Typing refers to the tendency of Ruby to be less concerned with the class of an object and more concerned with what methods can be called on it and what operations can be performed on it. In Ruby, we would use respond_to? or might simply pass an object to a method and know that an exception will be raised if it is used inappropriately.
If an object walks like a duck and talks like a duck, then the Ruby interpreter is happy to treat it as if it were a duck.
Consider the following example.
# Check in irb, whether the object defines the to_str method
>> 'A string'.respond_to?(:to str)
=> true
>> Exception.new.respond_to?(:to_str)
=> false
>> 4.respond_to?(:to_str)
=> false
The above example is the simplest example of Ruby's philosophy of "duck typing:" if an object quacks like a duck (or acts like a string), just go ahead and treat it as a duck (or a string). Whenever possible, you should treat objects according to the methods they define rather than the classes from which they inherit or the modules they include.
Now consider the following three classes - Duck, Goose and DuckRecording. Program p036duck.rb
Code
class Duck
def quack
'Quack!'
end
def swim
'Paddle paddle paddle...'
end
end
class Goose
def honk
'Honk!'
end
def swim
'Splash splash splash...'
end
end
class DuckRecording
def quack
play
end
def play
'Quack!'
end
end
def make_it_quack(duck)
duck.quack
end
puts make_it_quack(Duck.new)
puts make_it_quack(DuckRecording.new)
def make_it_swim(duck)
duck.swim
end
puts make_it_swim(Duck.new)
puts make_it_swim(Goose.new)
If you refer to the code shown below:
def make_it_quack(duck)
duck.quack
end
puts make_it_quack(Duck.new)
puts make_it_quack(DuckRecording.new)
A method that told a Duck to quack works when given a DuckRecoding, due to Duck Typing. Similarly in the following code:
def make_it_swim(duck)
duck.swim
end
puts make_it_swim(Duck.new)
puts make_it_swim(Goose.new)
A method that tells a Duck to swim when given a Goose, works.
Note: The Ruby Logo is Copyright (c) 2006, Yukihiro Matsumoto. I have made extensive references to information, related to Ruby, available in the public domain (wikis and the blogs, articles of various Ruby Gurus), my acknowledgment and thanks to all of them. Much of the material on rubylearning.github.io and in the course at rubylearning.org is drawn primarily from the Programming Ruby book, available from The Pragmatic Bookshelf.