+1

Duck Typing in Ruby

Duck Typing?

If you are familiar with Ruby, you'll have noticed that in Ruby we don't need to declare the types of the variables or return type of a method. This is one of the properties of dynamic programming language.

Some languages are statically typed, means the types are enforced at compile time. Languages like Java and C++ are statically typed languages. On the contrary, you have dynamically typed languages like Ruby and Python. Dynamic typing is more flexible and any type restrictions would have to be made at runtime.

Objects in Ruby, for example, are defined by the methods on them and not what type of thing they are. This idea of an object being defined by the messages it responds to is what duck typing is all about.

The name duck typing comes from the saying, “If it walks like a duck, and quacks like a duck, then it must be a duck.” In other words, If an object behaves like a duck then we will treat it like a duck, even if it isn't an actual duck.

Example

Consider these scenario,

class Egg
  def prepare
    puts "Egg is done."
  end
end

class Bread
  def prepare
    puts "Bread is done."
  end
end

class Breakfast
  def self.combo1
    Egg.new.prepare
    Bread.new.prepare
  end
end

Breakfast.combo1

We have 2 food classes here, Egg and Bread each with a method that will prepare the food for the Breakfast class. Another class Breakfast has a class method combo1. So if we want combo1 for breakfast we can just call this method. Nice.

By inspecting the combo1 method, we can clearly see that, this method dependent on 2 classes Egg and Bread. It relies on specific classes and has the explicit names of those classes. It knows the names of the messages that each class understands, along with the arguments that those messages require. All of this knowledge increases risk; many distant changes will now have side effects on this code.

Finding the duck

Both Egg and Bread classes serve the similar purpose prepare. It means, Egg and Bread both behaving like the same thing food (duck) and also contains similar action prepare (quack). So we can treat them both as a similar object and remove the direct dependencies from the combo1 method to make it more abstract, flexible and scalable. Refactored code will look like this,

class Breakfast
  def self.combo1 *foods
    foods.each do |food|
      food.prepare
    end
  end
end

Breakfast.combo1 Egg.new, Bread.new

Both Egg and Bread classes serve the similar purpose prepare. It means, Egg and Bread both behaving like the same thing food (duck) and also contains similar action prepare (quack). So we can treat them both as a similar object and remove the direct dependencies from the combo1 method to make it more abstract, flexible and scalable. If we need to add one more item to our Breakfast combo1 menu we can just pass that object as a param.

Breakfast.combo1 Egg.new, Bread.new, Butter.new

The code is more scalable now, right? It will be a lot easier to extend or improve some of the features in future and gives you more freedom.

Wrap up

Its pretty clear to see the flexibility that duck typing can bring to your application. Many of your favorite libraries and even the Ruby language itself makes heavy use of them. Duck typing will reduce many of the costly dependencies on classes and give you flexible environment to design your application. This will allow our objects to ask for what they want without knowing how to get it, and thus give us a more maintainable application.

References: http://www.poodr.com/ http://rubylearning.com/satishtalim/duck_typing.html https://revelry.co/duck-typing-with-ruby/


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí