2010/04/03

はじめての send

ISBN: 978-4048678841 | リファクタリング:Rubyエディション (大型本)

この本、私は対象読者ではなかった。飛ばし読みしていたらあっという間に p.165 までたどり着いてしまった。

そこで目にしたもの
p.165

サンプル
引数をまとめたHash を受け付けて、それらの引数をインスタンス変数に代入する SearchCriteria クラスがあるものとする。

とあり
p.166

Class.send :include, CustomInitilizers


send って何?といろいろ試してみた。

  1 #!/usr/local/bin/ruby191
  2 # coding: utf-8
  3 
  4 module Items
  5   module Setup
  6     def base(h)
  7       h.each{|k,v| self["@#{k}"] = v}
  8     end
  9     alias []= instance_variable_set
 10     alias [] instance_variable_get
 11   end
 12   class Music
 13     def initialize(h)
 14       self.base(h)
 15     end
 16   end
 17   class Book
 18     def initialize(h)
 19       base(h)
 20     end
 21   end
 22   Object.send :include, Setup
 23 end
 24 
 25 h = {:isbn=>'978xxx', :title=>'book-title', :price=>'1000'}
 26 p b = Items::Book.new(h)
 27 h = {:isbn=>'077xxx', :title=>'music-title', :price=>'2000'}
 28 p b = Items::Music.new(h)
 29 p b['@title']

=>
#<Items::Book:0xxxx @isbn="978xxx", @title="book-title", @price="1000">
#<Items::Music:0xxx @isbn="077xxx", @title="music-title", @price="2000">
"music-title"


最近知った あのaliasを使ってみた。

そして
「プログラミング言語 Ruby」p.285
を読み直した
Book.public_send :include, Setup
にしてもOKだった。

さらに
「Ruby Way」( Second edition)
にて send を探してみたら p.350 にsort_by のカスタムバージョン例の中で send を使う例があった。

self.sort{|x,y| x.send(sym) <=> y.send(sym)


この場合、x はArrayの要素でその要素のひとつひとつには Preson.new() Object が入っていて、
で、Presonの@name は attre_reader で読み込めるようになっている。ここがミソ。従ってソート対象として:name を指定することができる、と。
attre_writer :name だったらこれは成功しないだろう。
p.350 をジーとみているとうっかり send(@name)なのだと勘違いして理解しそうになるが、
send は「シンボル」を受けつけるのだから、send(@name) ではダメ。

+++ まとめ +++
send or public_send (Ruby 1.9) はシンボルを受けつける

module XXX
  module Setup ... end
  class Book ... end
  class Music ... end
  Object.send :include, Setup
end

Object.send とした場合は module が内包する[全て]のクラスのinclude メソッドに Setup module をおくりつけたことになる、と。
Object.send を Class.send としてみたら
`initialize': undefined method `base'
のエラーになった。

module XXX
  module Setup ... end
  class Book ... end
  class Music ... end
  Book.send :include, Setup
end

とした場合は module XXX が内包するBook クラスに[だけ]Setupをおくったことになる
従ってこの場合

module XXX
  module Setup ... end
  class Book
    include Setup
  end
end

と全くおなじ、と。

0 件のコメント: