ジョギング
日課
- 休み
fukuoka.rb
に参加した.
以下の 2 つのプルリクエストをこさえた.
今日のるびぃ ~ REx - Ruby Examination にチャレンジ (26) ~
REx - Ruby Examination の問題を自分なりにアレンジした上で 1 〜 3 問くらいずつ解いていく. 正直言ってかなり難しい. 尚, irb に動作確認環境は以下の通り.
$ ruby --version ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-linux] $ irb --version irb 0.9.6(09/06/30)
引き続き, class_eval による定数参照
以下のコードは Hello, world
を表示する. 同じ結果となるコードを複数選択する.
module M CONST = "Hello, world" class C def awesome_method CONST end end end p M::C.new.awesome_method
以下, 解答.
# 解答(1) class C end module M CONST = "Hello, world" C.class_eval do def awesome_method CONST end end end p C.new.awesome_method # 解答 (2) class C CONST = "Hello, world" end module M C.class_eval(<<-CODE) def awesome_method CONST end CODE end p C.new.awesome_method
以下, irb にて確認.
# 設問コード irb(main):001:0> module M irb(main):002:1> CONST = "Hello, world" irb(main):003:1> irb(main):004:1* class C irb(main):005:2> def awesome_method irb(main):006:3> CONST irb(main):007:3> end irb(main):008:2> end irb(main):009:1> end => :awesome_method irb(main):010:0> irb(main):011:0* p M::C.new.awesome_method "Hello, world" => "Hello, world" # 解答(1) irb(main):001:0> class C irb(main):002:1> end => nil irb(main):003:0> irb(main):004:0* module M irb(main):005:1> CONST = "Hello, world" irb(main):006:1> irb(main):007:1* C.class_eval do irb(main):008:2* def awesome_method irb(main):009:3> CONST irb(main):010:3> end irb(main):011:2> end irb(main):012:1> end => :awesome_method irb(main):013:0> irb(main):014:0* p C.new.awesome_method "Hello, world" => "Hello, world" # 解答(2) irb(main):001:0> class C irb(main):002:1> CONST = "Hello, world" irb(main):003:1> end => "Hello, world" irb(main):004:0> irb(main):005:0* module M irb(main):006:1> C.class_eval(<<-CODE) irb(main):007:2" def awesome_method irb(main):008:2" CONST irb(main):009:2" end irb(main):010:2" CODE irb(main):011:1> end => :awesome_method irb(main):012:0> irb(main):013:0* p C.new.awesome_method "Hello, world" => "Hello, world"
以下, 解説より抜粋.
- 解答 (1)
- class_eval にブロックを渡した場合は, ブロック内のネストはモジュール M になる
- そのコンテキストから定数を探索するので "Hello, world" が表示される
- 解答 (2)
- class_eval に文字列を渡した場合のネストの状態はクラス C となる
- CONST はクラス C にある為, "Hello, world" が表示される
念の為, ブロックで渡した場合と, 文字列で渡した場合のネストの状態を確認してみる.
# class_eval のブロック渡し irb(main):001:0> class C irb(main):002:1> end => nil irb(main):003:0> irb(main):004:0* module M irb(main):005:1> C.class_eval do irb(main):006:2* Module.nesting irb(main):007:2> end irb(main):008:1> end => [M] irb(main):009:0> exit # class_eval の文字列渡し irb(main):001:0> class C irb(main):002:1> end => nil irb(main):003:0> irb(main):004:0* module M irb(main):005:1> C.class_eval(<<-CODE) irb(main):006:2" Module.nesting irb(main):007:2" CODE irb(main):008:1> end => [C, M]
上記のように, ネストの状態が異なる為, 定数を探索するコンテキストも異なることが解る.
フムフム.