ジョギング
日課
- (腕立て x 50 + 腹筋 x 50) x 3
ワールドカップ
- 日本がコロンビアに 2 - 1 で勝った
- 長友選手の運動量が半端ないなーと思った, あの持久力には驚き...
今日のるびぃ ~ REx - Ruby Examination にチャレンジ (31) ~
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)
クラス, メソッドの優先順位
以下のコードを実行するとどうなるか.
module Mod1 end module Mod2 end class Cls include Mod1, Mod2 end p Cls.ancestors
[Cls, Mod1, Mod2, Object, Kernel, BasicObject]
以下, irb による確認.
irb(main):001:0> module Mod1 irb(main):002:1> end => nil irb(main):003:0> irb(main):004:0* module Mod2 irb(main):005:1> end => nil irb(main):006:0> irb(main):007:0* class Cls irb(main):008:1> include Mod1, Mod2 irb(main):009:1> end => Cls irb(main):010:0> irb(main):011:0* p Cls.ancestors [Cls, Mod1, Mod2, Object, Kernel, BasicObject] => [Cls, Mod1, Mod2, Object, Kernel, BasicObject
include
やprepend
はモジュールのメソッドをインスタンスメソッドとして追加するinclude
では, メソッド探索順はself
の後に追加され,prepend
では,self
の前に追加される- 複数モジュールを指定した場合は, 左側が先にメソッド探索される
ちなみに, prepend
した場合には, 以下のように出力される.
irb(main):015:0> Cls2.ancestors => [Mod1, Mod2, Cls2, Object, Kernel, BasicObject]
定数探索
以下のコードを実行するとどうなるか.
module Mod1 def refer_const CONST end end module Mod2 CONST = '010' end class Cls1 CONST = "001" end class Cls2 < Cls1 include Mod2 include Mod1 CONST = '100' end c = Cls2.new p c.refer_const
例外が発生する
以下, irb にて確認.
irb(main):001:0> module Mod1 irb(main):002:1> def refer_const irb(main):003:2> CONST irb(main):004:2> end irb(main):005:1> end => :refer_const irb(main):006:0> irb(main):007:0* module Mod2 irb(main):008:1> CONST = '010' irb(main):009:1> end => "010" irb(main):010:0> irb(main):011:0* class Cls1 irb(main):012:1> CONST = "001" irb(main):013:1> end => "001" irb(main):014:0> irb(main):015:0* class Cls2 < Cls1 irb(main):016:1> include Mod2 irb(main):017:1> include Mod1 irb(main):018:1> CONST = '100' irb(main):019:1> end => "100" irb(main):020:0> irb(main):021:0* c = Cls2.new => #<Cls2:0x0055a24afb1b10> irb(main):022:0> p c.refer_const NameError: uninitialized constant Mod1::CONST
以下, 解説より抜粋.
refer_const
メソッドは, モジュール Mod1 にあるが,CONST
はレキシカルに決定されるためモジュールMod1
のスコープを探索する- 設問では
Mod1
内にCONST
が見つからないため例外が発生する
例えば, 以下のように書くことで Mod1::CONST
を参照することが出来る.
irb(main):001:0> module Mod1 irb(main):002:1> CONST = '100' irb(main):003:1> def refer_const irb(main):004:2> CONST irb(main):005:2> end irb(main):006:1> end => :refer_const irb(main):007:0> irb(main):008:0* module Mod2 irb(main):009:1> CONST = '010' irb(main):010:1> end => "010" irb(main):011:0> irb(main):012:0* class Cls1 irb(main):013:1> CONST = "001" irb(main):014:1> end => "001" irb(main):015:0> irb(main):016:0* class Cls2 < Cls1 irb(main):017:1> include Mod2 irb(main):018:1> include Mod1 irb(main):019:1> end => Cls2 irb(main):020:0> irb(main):021:0* c = Cls2.new => #<Cls2:0x00556bfc9497e8> irb(main):022:0> p c.refer_const "100" => "100"
フムフム.