Generally if your class has an array/hash, sometimes you don’t want to expose the implementation of those collections outside of the object. Creating your own iterator will make your object easier to use.
class Headphone attr_reader :name, :brand, :version def initialize(name, brand, version) @name = name @brand = brand @version = version @accessories = [] end def add_accessory(name) @accessories << name end def each_accessory @accessories.each { |x| yield x.name } end end Accessory = Struct.new(:name, :color) a1 = Accessory.new("Headphone cable", :black) a2 = Accessory.new("Connector Adapter", :gold) a3 = Accessory.new("Carrying Pouch", :gray) a4 = Accessory.new("Earpds", :brown) a = Headphone.new("AudioTechnica", "M50X", 1.0) a.add_accessory(a1) a.add_accessory(a2) a.add_accessory(a3) a.add_accessory(a4) a.each_accessory do |x| puts "Accessory: #{x}" end # Accessory: Headphone cable # Accessory: Connector Adapter # Accessory: Carrying Pouch # Accessory: Earpds
I think another way to demonstrate this is to show how the “each” and “times” methods work in Ruby. There isn’t much magic involved. For times all you have to do is open up the Integer class and define your own with a while loop:
class Integer def my_times i = 0 while i < self yield i i += 1 end end end 13.my_times do |x| puts x end Output: 0 1 2 3 4 5 6 7 8 9 10 11 12
As for each it’s very similar:
class Array def my_each i = 0 while i < self.size yield self[i] i += 1 end end end types_of_bacon = ["Canadian", "Turkey", "Cottage", "Smoked"] types_of_bacon.my_each do |b| puts b end Output: Canadian Turkey Cottage Smoked
Hopefully this helps demystify these methods we use and love so much.
Recent Comments