ようへいの日々精進XP

よかろうもん

2018 年 06 月 19 日 (火)

ジョギング

  • お昼休みに自宅→香椎神宮香椎浜 で 35 分くらい
  • 引き続き, 臀部の強い張り (ストレッチでなんとかしている)
  • 左足足底筋にも違和感あり

日課

  • (腕立て 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
  • includeprepend はモジュールのメソッドをインスタンスメソッドとして追加する
  • 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"

フムフム.