ジョギング
- 今日はお休み
- 足もだるいし, 体もキツかったので
日課
- ついでに休み
香椎宮
- お参りに行った
- お昼ごはんは香椎宮近くの中華屋さんで, 美味しかった
今日のるびぃ ~ REx - Ruby Examination にチャレンジ (6) ~
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 Cls1 CONST = "AAA" def self.name const_get(:CONST) end end class Cls2 < Cls1 CONST = "BBB" end puts Cls2.name
BBB と出力される
以下, irb による確認.
irb(main):001:0> class Cls1 irb(main):002:1> CONST = "AAA" irb(main):003:1> irb(main):004:1* def self.name irb(main):005:2> const_get(:CONST) irb(main):006:2> end irb(main):007:1> end => :name irb(main):008:0> irb(main):009:0* class Cls2 < Cls1 irb(main):010:1> CONST = "BBB" irb(main):011:1> end => "BBB" irb(main):012:0* puts Cls2.name BBB => nil
以下, 解説より抜粋.
Cls1#name
はClass#name
をオーバーライトしている為,const_get
が呼ばれるconst_get
は, self に定義されている定数を探索する. 自クラスに定義がない場合は、メソッドと同様に探索を行う- 設問の 5 行目時点のインスタンスは Cls2 クラスで,
Cls1#name
は Cls2 クラスの定数の値BBB
を返します。
解説がイマイチ理解出来なかったので, 自分なり irb を使って確認.
Cls1#name
はClass#name
をオーバーライトしている為,const_get
が呼ばれる
Class クラスに name というメソッドってあるのかな...と思ったら, 以下のように存在している.
irb(main):016:0> Class.methods.grep(/name/) => [:name]
これは, Module#name を継承している為, name メソッドを呼び出すことが出来る. このメソッド自体は, 以下の実行例のように, モジュールやクラスの名前を返す機能があるが, 設問ではオープンクラスしてこの機能を const_get
の結果を返すように上書きしている.
irb(main):001:0> class Cls1; end => nil irb(main):002:0> Cls1.name => "Cls1" irb(main):003:0> class Cls1 irb(main):004:1> def self.name irb(main):005:2> puts 'fooo' irb(main):006:2> end irb(main):007:1> end => :name irb(main):008:0> Cls1.name fooo => nil
上記では, Class#name
を fooo
を puts するように上書き (機能変更) している.
const_get
は, self に定義されている定数を探索する. 自クラスに定義がない場合は、メソッドと同様に探索を行う
以下のように定数の探索が行われている.
irb(main):001:0> module Mod1 irb(main):002:1> CONST = 'Mod1' irb(main):003:1> end => "Mod1" irb(main):004:0> irb(main):005:0* class Cls1 irb(main):006:1> CONST = 'Cls1' irb(main):007:1> end => "Cls1" irb(main):008:0> irb(main):009:0* class Cls2 < Cls1 irb(main):010:1> def self.name irb(main):011:2> const_get(:CONST) irb(main):012:2> end irb(main):013:1> end => :name irb(main):014:0> Cls2.name => "Cls1" ... irb(main):001:0> module Mod1 irb(main):002:1> CONST = 'Mod1' irb(main):003:1> end => "Mod1" irb(main):004:0> irb(main):005:0* class Cls1 irb(main):006:1> CONST = 'Cls1' irb(main):007:1> end => "Cls1" irb(main):008:0> irb(main):009:0* class Cls2 < Cls1 irb(main):010:1> include Mod1 irb(main):011:1> def self.name irb(main):012:2> const_get(:CONST) irb(main):013:2> end irb(main):014:1> end => :name irb(main):015:0> Cls2.name => "Mod1"
フムフム.