Ruby 2 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.
  1. # Check in irb, whether the object defines the to_str method  
  2. >> 'A string'.respond_to?(:to str)  
  3. => true  
  4. >> Exception.new.respond_to?(:to_str)  
  5. => false  
  6. >> 4.respond_to?(:to_str)  
  7. => 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

  1. class Duck  
  2.   def quack  
  3.     'Quack!'  
  4.   end  
  5.   
  6.   def swim  
  7.     'Paddle paddle paddle...'  
  8.   end  
  9. end  
  10.   
  11. class Goose  
  12.   def honk  
  13.     'Honk!'  
  14.   end  
  15.   def swim  
  16.     'Splash splash splash...'  
  17.   end  
  18. end  
  19.   
  20. class DuckRecording  
  21.   def quack  
  22.     play  
  23. end  
  24.   
  25.   def play  
  26.     'Quack!'  
  27.   end  
  28. end  
  29.   
  30. def make_it_quack(duck)  
  31.   duck.quack  
  32. end  
  33. puts make_it_quack(Duck.new)  
  34. puts make_it_quack(DuckRecording.new)  
  35.   
  36. def make_it_swim(duck)  
  37.   duck.swim  
  38. end  
  39. puts make_it_swim(Duck.new)  
  40. puts make_it_swim(Goose.new)  
If you refer to the code shown below:
  1. def make_it_quack(duck)  
  2.   duck.quack  
  3. end  
  4. puts make_it_quack(Duck.new)  
  5. 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:
  1. def make_it_swim(duck)  
  2.   duck.swim  
  3. end  
  4. puts make_it_swim(Duck.new)  
  5. puts make_it_swim(Goose.new)  
A method that tells a Duck to swim when given a Goose, works.