ジョギング
日課
- (腕立て x 50 + 腹筋 x 50) x 3
夕飯
- 山芋とピーマンに小麦粉をふって素揚げにしたら美味しかった
- サーモンも軽く粉して素揚げ風で美味しかった
今日のるびぃ ~ REx - Ruby Examination にチャレンジ (2) ~
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 C CONST = "A" end module M CONST = "B" end module M class C CONST = "C" end end module M class C p CONST end end module M class C p CONST p ::C::CONST p ::M::CONST end end
C
以下, irb による確認.
irb(main):001:0> class C irb(main):002:1> CONST = "A" irb(main):003:1> end => "A" irb(main):004:0> irb(main):005:0* module M irb(main):006:1> CONST = "B" irb(main):007:1> end => "B" irb(main):008:0> irb(main):009:0* module M irb(main):010:1> class C irb(main):011:2> CONST = "C" irb(main):012:2> end irb(main):013:1> end => "C" irb(main):014:0> irb(main):015:0* module M irb(main):016:1> class C irb(main):017:2> p CONST irb(main):018:2> end irb(main):019:1> end "C" => "C"
以下, メモ.
- 冒頭の
C
とM::C
は別物となる - 設問の場合は
M::C
にあるCONST
が参照される為,C
が表示される
ちなみに, 以下のように書くことで, 全ての定数を参照することが出来る.
irb(main):028:0> p M::C::CONST "C" => "C" irb(main):029:0> p ::C::CONST "A" => "A" irb(main):030:0> p ::M::CONST "B" => "B"
オブジェクト指向, 定数探索
次のプログラムは "ABCDEFG" と表示するが, 同じ結果になる選択肢はどれか (複数選択).
module M CONST = "ABCDEFG" class C def awesome_method CONST end end end p M::C.new.awesome_method
一応, 上記のコードを irb で確認.
irb(main):001:0> module M irb(main):002:1> CONST = "ABCDEFG" 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 "ABCDEFG" => "ABCDEFG"
フムフム.
選択肢を見ていて, 随所に出てきていた class_eval
が解らなかったので, 以下, ドキュメントより引用.
モジュールのコンテキストで文字列 expr またはモジュール自身をブロックパラメータとするブロックを 評価してその結果を返します。
モジュール内でメソッドを動的に定義する為に利用する...という解釈.
irb(main):001:0> class C irb(main):002:1> end => nil irb(main):003:0> a = 1 => 1 irb(main):004:0> C.class_eval %Q{ irb(main):005:0" def m irb(main):006:0" return :m, #{a} irb(main):007:0" end irb(main):008:0" } => :m irb(main):009:0> C.new.m => [:m, 1]
ナルホド...
class_eval の定数とローカル変数の参照については, 以下のように記載されている.
文字列が与えられた場合には、定数とクラス変数のスコープは自身のモジュール定義式内と同じスコープになります。 ブロックが与えられた場合には、定数とクラス変数のスコープはブロックの外側のスコープになります。
# 以下, ブロックが与えられたパターン class C CONST = "ABCDEFG" end module M C.class_eval do def awesome_method CONST end end end p C.new.awesome_method # 以下, 文字列が与えられているパターン class C CONST = "ABCDEFG" end module M C.class_eval(<<-CODE) def awesome_method CONST end CODE end p C.new.awesome_method
一見, 同じ結果になりそうな気がするけど, 以下のような違いがある.
- ブロックが与えられたパターン
irb(main):012:0> p C.new.awesome_method NameError: uninitialized constant M::CONST from (irb):8:in `awesome_method' from (irb):12 from /usr/local/bin/irb:11:in `<main>'
- 文字列が与えられているパターン
# 以下, 文字列が与えられているパターン irb(main):012:0> p C.new.awesome_method "ABCDEFG" => "ABCDEFG"
フムフム.
ちょっとスッキリしないけど...