ジョギング
- 香椎浜 x 2
- どうも走りがギクシャクしていて, たった 2 周しかしていないのに, 足の疲労感も半端ない
日課
- (腕立て x 50 + 腹筋 x 30) x 3
奥さん
- 寒暖差が大きくなってきているので, 少し体調を崩した感じ
- せっかく暖かくなったのに..., 明日は休んで養生して欲しい
今日のるびぃ ~ ブランクスレート ~
引き続き, メタプログラミングRuby 第2版 の読書メモ.
ブランクスレート
- 最小限のメソッドしかない状態のクラス
- スーパークラスの継承したメソッドが不要であれば, それを削除することで衝突を回避出来る
BasicObject
- スーパークラスを指定しなければデフォルトで Object クラスを継承する
- Object クラスは BasicObject のサブクラス
[5] pry(main)> BasicObject.instance_methods => [:!, :equal?, :__binding__, :instance_eval, :instance_exec, :==, :!=, :__id__, :__send__] [6] pry(main)> BasicObject.instance_methods.count => 9 [7] pry(main)> Object.instance_methods.count => 65
例
こちらより抜粋.
class Proxy < BasicObject def initialize(target) @target = target end def method_missing(message, *args) @target.__send__(message, *args) end end
これを実行すると...
[1] pry(main)> class Proxy < BasicObject [1] pry(main)* def initialize(target) [1] pry(main)* @target = target [1] pry(main)* end [1] pry(main)* [1] pry(main)* def method_missing(message, *args) [1] pry(main)* @target.__send__(message, *args) [1] pry(main)* end [1] pry(main)* end => :method_missing [2] pry(main)> Proxy.new(1).to_s # method_missing を介して 1.to_s が呼ばれる => "1" [3] pry(main)> Proxy.new(1).to_f # method_missing を介して 1.to_f が呼ばれる => 1.0 [4] pry(main)> Proxy.new(1) + 2 # method_missing を介して 1 + 2 が呼ばれる... Ruby では + もメソッド :desuyone: => 3 [5] pry(main)> Proxy.new(1).display 1=> nil
極端な method_missing と BasicObject な例
class Cls1 def method_missing(method, *args) puts "called #{method}(#{args.join(', ')})" end end Cls1.new.display
これを実行すると...
[15] pry(main)> class Cls1 [15] pry(main)* def method_missing(method, *args) [15] pry(main)* puts "called #{method}(#{args.join(', ')})" [15] pry(main)* end [15] pry(main)* end => :method_missing [16] pry(main)> [17] pry(main)> Cls1.new.display #<Cls1:0x000055f0aca64058>=> nil
Object#dispaly が呼ばれている雰囲気. これを BasicObject を継承してブランクスレートすると...
class Cls1 < BasicObject def method_missing(method, *args) puts "called #{method}(#{args.join(', ')})" end end Cls1.new.display
BasicObject を継承してブランクスレートすると...
[1] pry(main)> class Cls1 < BasicObject [1] pry(main)* def method_missing(method, *args) [1] pry(main)* puts "called #{method}(#{args.join(', ')})" [1] pry(main)* end [1] pry(main)* end => :method_missing [2] pry(main)> [3] pry(main)> Cls1.new.display SystemStackError: stack level too deep from (pry):3:in `method_missing'
とうとう呼ばれるメソッドが無くなって SystemStackError: stack level too deep
となり無限ループとなる (呼び出すメソッドが存在していない為)
ふむふむ.