Thursday, July 29, 2010

Rubyの特異メソッドと特異クラス

プログラミング言語Ruby P269辺りに特異メソッドと特異クラスについての解説がある。
読んだだけじゃ絶対にわすれるので、メモっとく。

特異メソッド
クラスに属するすべてのオブジェクトではなく、単一のオブジェクトだけのために定義されたメソッド
オブジェクトの特異メソッドは、そのオブジェクトのクラスによって定義されない。
そのオブジェクトに対応付けられた無名の特異クラスのインスタンスメソッドである。
無名の特異クラスのことをシングルトンクラス、メタクラスと呼ぶ。

各インスタンスごとに特異クラスを持つ。
classのインスタンスClass1の特異メソッドは、Class1クラスのクラスメソッドであり、
classのインスタンスであるClass1の特異クラスのインスタンスメソッドである。

試してみた。

  1. # ClassクラスのインスタンスであるPointオブジェクトに特異メソッドを定義  
  2. # Pointクラスのクラスメソッドになる  
  3. class Point; end  
  4. def Point.sum x, y; x + y; end  
  5. p Point.sum 1,2  #=> 3  
  6.   
  7. # 特異メソッドを複数定義時に便利な構文糖  
  8. class << Point  
  9.   def minus x, y; x - y; end  
  10.   def multi x, y; x * y; end  
  11. end  
  12. p Point.minus 1,2  #=> -1  
  13. p Point.multi 1,2  #=> 2  
  14.   
  15. # クラス定義中にクラスメソッドを複数定義するときに便利な構文糖  
  16. # class << self は特異クラス(classのインスタンスであるPointクラスオブジェクト)  
  17. class Point  
  18.   class << self  
  19.     def div x, y; x / y; end  
  20.   end  
  21.   def self.eignclass   
  22.     class << selfselfend  
  23.   end  
  24. end  
  25.   
  26. # p1オブジェクトの特異メソッドを定義  
  27. p1 = Point.new  
  28. def p1.sum x, y, z; x + y + z; end  
  29. p p1.sum(1, 2, 3) #=> 6  
  30.   
  31. # p2からはp1の特異メソッドは見えない  
  32. p2 = Point.new  
  33. #p p2.sum(1, 2, 3) #=> NoMethodError  
  34.   
  35. class << p2  
  36.   def sum x, y ,z, a; x + y + z + a; end  
  37.   def multi x, y ,z, a; x * y * z * a; end  
  38. end  
  39. p p2.sum 1, 2, 3, 4 #=> 10  
  40. p p2.multi 1, 2, 3, 4 #=> 24  
  41.   
  42. # p2からはP1特異メソッド特異メソッドは見えない  
  43. #p p1.sum 1, 2, 3, 4 #=> NoMethodError  
  44.   
  45. # 実行結果  
  46. # 3  
  47. # -1  
  48. # 2  
  49. # 6  
  50. # 10  
  51. # 24  

もう一丁。

  1. class Class1  
  2.   puts "#{self.__id__} before open singleton class"  
  3.   class << self  
  4.     puts "#{self.__id__} opening singleton class"  
  5.   end  
  6.   def self.eignclass   
  7.     class << selfselfend  
  8.   end  
  9.   puts "<<< " + self.to_s  
  10. end  
  11.   
  12. class Class2  
  13.   puts ">>> " + self.to_s  
  14.   puts "#{self.__id__} before open singleton class"  
  15.   class << self  
  16.     puts "#{self.__id__} opening singleton class"  
  17.   end  
  18.   def self.eignclass   
  19.     class << selfselfend  
  20.   end  
  21.   puts "<<< " + self.to_s  
  22. end  
  23. puts "------------"  
  24. puts "#{Class1.__id__} Class1.__id__"  
  25. puts "#{Class1.eignclass.__id__} Class1.eignclass.__id__"  
  26.   
  27. puts "------------"  
  28. puts "#{Class2.__id__} Class2.__id__"  
  29. puts "#{Class2.eignclass.__id__} Class2.eignclass.__id__"  
  30.   
  31. puts "------------"  
  32. c1 = Class1.new  
  33. puts "#{c1.__id__} c1's id"  
  34. class << c1   
  35.   puts "#{self.__id__} c1's singleton class"  
  36. end  
  37.   
  38. puts "------------"  
  39. c11 = Class1.new  
  40. puts "#{c11.__id__} c11's id"  
  41. class << c11  
  42.   puts "#{self.__id__} c11's singleton class"  
  43. end  
  44.   
  45. puts "------------"  
  46. c2 = Class2.new  
  47. puts "#{c2.__id__} c2's id"  
  48. class << c2   
  49.   puts "#{self.__id__} c2's singleton class"  
  50. end  
  51.   
  52. puts "------------"  
  53. c21 = Class2.new  
  54. puts "#{c21.__id__} c21's id"  
  55. class << c21  
  56.   puts "#{self.__id__} c21's singleton class"  
  57. end  
  58.   
  59. # 実行結果  
  60. # >>> Class1  
  61. # 70227334526040 before open singleton class  
  62. # 70227334526020 opening singleton class  
  63. # <<< Class1  
  64. # >>> Class2  
  65. # 70227334525980 before open singleton class  
  66. # 70227334525680 opening singleton class  
  67. # <<< Class2  
  68. # ------------  
  69. # 70227334526040 Class1.__id__  
  70. # 70227334526020 Class1.eignclass.__id__  
  71. # ------------  
  72. # 70227334525980 Class2.__id__  
  73. # 70227334525680 Class2.eignclass.__id__  
  74. # ------------  
  75. # 70227334525100 c1's id  
  76. # 70227334525040 c1's singleton class  
  77. # ------------  
  78. # 70227334524940 c11's id  
  79. # 70227334524880 c11's singleton class  
  80. # ------------  
  81. # 70227334524780 c2's id  
  82. # 70227334524720 c2's singleton class  
  83. # ------------  
  84. # 70227334524620 c21's id  
  85. # 70227334524560 c21's singleton class  

Thursday, July 22, 2010

Rubyのクラスメソッド

プログラミング言語Ruby(P268)

クラスのクラスメソッドとは、そのクラスを表現するClassクラスのインスタンスの特異メソッドにすぎない。

RubyのModule, Class, include, extend, selfポインタ

プログラミング言語Ruby P258の内容のサンプル。

クラス階層が必要のないグローバル関数を、グローバルな名前空間を汚さないためにModuleとしてまとめる方法。
moduleに定義したインスタンスメソッドをmix-inする方法( include, extend)
includeはインスタンスメソッドとして織りまぜ、
extendは特異メソッドとして織りまぜる。

  1. module SampleModule  
  2.   
  3.   # class method  
  4.   def self.hello  
  5.     puts "hello"  
  6.   end  
  7.   
  8.   # class method  
  9.   def self.goodby  
  10.     puts "goodby"  
  11.   end  
  12.   
  13.   # instance method  
  14.   def good_morning  
  15.     puts "good_morning"  
  16.   end  
  17. end  
  18.   
  19. class IncludeMod  
  20.   # インスタンスメソッドとしてinclude  
  21.   include SampleModule  
  22. end  
  23.   
  24. class ExtendMod  
  25.   # クラスメソッドとしてextend  
  26.   # この時のselfはクラスの中、メソッド定義の外なので ExtendModクラスをサス(P225)  
  27.   self.extend SampleModule  
  28.   #ExtendMod.extend SampleModule  
  29. end  
  30.   
  31. SampleModule.hello  
  32. SampleModule.goodby  
  33.   
  34. IncludeMod.new.good_morning  
  35. ExtendMod.good_morning  

Rubyの継承時のprivateメソッドには注意

プログラミング言語Ruby P248

サブクラスはPrivateメソッドを継承する。
サブクラスは親で定義されたprivateメソッドを呼び出せ、オーバーライドすることが可能。

他人が書いたクラスをサブクラス化するときは気をつけろ。
偶然、同じ名前のprivateメソッドをオーバーライドするとバグる。

Rubyではサブクラス化するのは、スーパークラスの実装を欲知っている時に限るべきだ。
継承ではなく、委譲するべき。

Ruby1.9からSymbolクラスにto_procが追加されたってか

プログラミング言語Rubyを読んでいる。
P217に、Ruby1.9からSynbolクラスにto_procが追加されたので、シンボルに&プレフィックスを付けると、イテレータにブロックとして渡せるようになった、と書いてある。

メモメモ。

  1. def succ x; x + 1; end  
  2. p [1,2,3].map{|x| x + 1}  
  3. p [1,2,3].map{|x| succ x}  
  4. p [1,2,3].map(&:succ)  
  5. p [1,2,3].map(&self.method(:succ))  
  6. p [1,2,3].map{|x| self.method(:succ).call(x) }  
  7. p [1,2,3].map{|x| self.method(:succ).to_proc.call(x) }  

Wednesday, July 21, 2010

Rubyで関数を継承?

勉強のためにRubyのライブラリでも見ていくことにした。
とりあえず一発目はtempfile.rbでも見てみるかということで、13行目。

  1. class Tempfile < DelegateClass(File)  
ほうほう、DelegateClassを継承しているのね。でも括弧なんだろ? おもむろにCtagsで飛んでみた。(delegate.rb) そしたら、ビックリ。
  1. def DelegateClass(superclass)  
関数じゃないですか。

分からん。。
また分かったら追記するってことでメモっておく。

追記
わかった。
def DelegateClass(superclass)
はクラスを返すメソッドなのね。

Delegate(クラス)で指定したクラスのpublic instance methodと
__getobj__, __setobj__をmodule_evalしたクラスを
継承したいからこんなことしてるのか。

Thursday, July 1, 2010

vrome 0.5.7 (chrome extention)でページ内日本語検索ができんぞ

/(スラッシュ)でページ内を日本語で検索しようとしても検索できない。
アルファベットならいけるけど。
Ctrl + fもnext pageに割り当ててられていて使えない。

不便過ぎて発狂しそうになったので、extentionのソースを変更してCtrl + f でChromeの検索窓が出るようにした。


kanbe@kanbe-laptop% locate vrome
/home/kanbe/.config/google-chrome/Default/Extensions/godjoomfiimiddapohpmfklhgmbfffjj/0.5.7/vromerc_example

kanbe@kanbe-laptop% cd /home/kanbe/.config/google-chrome/Default/Extensions/godjoomfiimiddapohpmfklhgmbfffjj/0.5.7
kanbe@kanbe-laptop% grep "<c-f>" **/*
frontend/main.js:  add("<c-f>" , Scroll.nextPage     );
..




main.jsのadd...をコメントアウトで終了。