"When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck." Duck types are public interfaces that are not tied to any specific class. They are about the object's methods and properties, rather that its inheritance from a certain class. In a nutshell:
Behaviour over class membership
Following that pattern helps to improve:
- readability (less code for all message sender)
 - add enormous flexibility
 - reduces class coupling and therefore increases maintainability
 
class Drug
  attr_accessor :dope, :brand
end
class Food
  attr_accessor :ingredients
  def labeling
    ingredients.map { |ingredient| ingredient.name }.join(', ')
  end
end
class Clothing
  attr_accessor :name
end
and a Bill class for printing out:
class Bill
  def print_name product
    return puts "#{product.brand} (#{product.dope})" if product.respond_to? :dope
    return puts product.labeling if product.respond_to? :labeling
    puts product.name
  end
end
The Bill#print_name can be refactored by also duck typing the 3 classes:
class Drug
  attr_accessor :dope, :brand
  def name
    "#{product.brand} (#{product.dope})"
  end
end
class Food
  attr_accessor :ingredients
  def labeling
    ingredients.map { |ingredient| ingredient.name }.join(', ')
  end
  alias_method :name, :labeling
end
class Clothing
  attr_accessor :name
end
All 3 classes now respond to name and can called in Bill#print_name like:
class Bill
  def print_name product
    puts product.name
  end
end
Further articles of interest:Supported by Ruby 2.1.1
Keine Kommentare:
Kommentar veröffentlichen