メソッドの移譲について学んだのでメモです。
参考 実行環境 実装 Forwardable を使っていないパターン test3.rb 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 require  'ostruct' class  Stock   attr_reader  :items    def  initialize (items )     @items  = items |   end    def  last_ones      items.select{|i | i.count == 1  }   end  end item1 = OpenStruct .new({ name:  "saba" , count:  3  }) item2 = OpenStruct .new({ name:  "maguro" , count:  1  }) def  format_item (i ) = "#{i.name} :#{i.count} 個" stock = Stock .new([item1, item2]) stock.items.each{|i | puts format_item(i) } stock.last_ones.each{|i | puts format_item(i) } 
Forwardable を使ってみる test2.rb 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 require  'forwardable' require  'ostruct' class  Stock   extend  Forwardable    def_delegators : @items , :each    def  initialize (items )     @items  = items |   end    def  last_ones      @items .select{|i | i.count == 1  }   end  end item1 = OpenStruct .new({ name:  "saba" , count:  3  }) item2 = OpenStruct .new({ name:  "maguro" , count:  1  }) def  format_item (i ) = "#{i.name} :#{i.count} 個" stock = Stock .new([item1, item2]) stock.each{|i | puts format_item(i) } stock.last_ones.each{|i | puts format_item(i) } 
Stack に対して、each を呼び出すと応答するオブジェクトが @items に代わっている。
変更前は、itemsに問い合わせる必要がある。(ということを知っている必要がある。)
1 stock.items.each{|i | puts format_item(i) } 
変更後は、インスタンスに直接問い合わせるだけで OK。
1 stock.each{|i | puts format_item(i) } 
Enumerable も使ってみる Enumerable は、繰り返し処理を行うための Mix-in だそう。
test3.rb 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 require  'forwardable' require  'ostruct' class  Stock   extend  Forwardable    def_delegators : @items , :each    include  Enumerable    def  initialize (items )     @items  = items |   end    def  last_ones      select{|i | i.count == 1  }   end  end item1 = OpenStruct .new({ name:  "saba" , count:  3  }) item2 = OpenStruct .new({ name:  "maguro" , count:  1  }) def  format_item (i ) = "#{i.name} :#{i.count} 個" stock = Stock .new([item1, item2]) stock.each{|i | puts format_item(i) } stock.last_ones.each{|i | puts format_item(i) } 
Stockクラスに、Enumerableを読みこむことでselectメソッドを備えることができるようになりました。Enumerableは、クラスが each メソッドを備えることが必要であるので、ほとんどForwardableでeachを移譲するのがセットの運用と考えられそう。eachメソッドを別途作っている記事を見かけたので、またあとで試そうかと。)
ファクトリパターンを作ってみる。 これらを使ってファクトリパターンの実装を試してみます。
test4.rb 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 require  'forwardable' require  'ostruct' class  Stock   extend  Forwardable    def_delegators : @items , :each , :push    include  Enumerable    def  initialize (items )     @items  = items |   end    def  last_ones      select{|i | i.count == 1  }   end  end module  StockFactory      def  self .build(config)     items = config.collect {|c | OpenStruct .new({ name:  c[0 ], count:  c[1 ] })}     Stock .new(items)   end  end def  format_item (i ) = "#{i.name} :#{i.count} 個" config = [["saba" ,3  ], ["maguro" , 1 ]] add_item = OpenStruct .new({ name:  "tara" , count:  4  }) stock = StockFactory .build(config) stock.each{|i | puts format_item(i) } stock.last_ones.each{|i | puts format_item(i) } stock.push(add_item) stock.each{|i | puts format_item(i) } 
ファクトリーパターンの適用とともに、pushメソッドも移譲をしてみました。
今回は、Forwardable モジュールでのメソッド移譲を手始めに、ファクトリーパターンの実装を試しました。eachといったメソッドを移譲させられると、中のデータをオブジェクトの外に晒さなくて良くなるのは利点と感じます。
今回、Forwardable や Enumerable を試しましたが、標準で用意されているライブラリについての認識持っておくのって絶対大事ですね。
ではでは。