ジョギング
日課
- (腕立て x 50 + 腹筋 x 50) x 3
今日のるびぃ ~ REx - Ruby Examination にチャレンジ (34) ~
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#refine
以下のコードを実行するとどうなるか.
class Cls1 def method1(value) 100 + value end end module Mod1 refine Cls1 do def method1 super 50 end end end module Mod2 refine Cls1 do def method1 super 100 end end end using Mod1 using Mod2 puts Cls1.new.method1
以下, 解答.
200 が出力される
以下, 確認. refine を含むコードは irb で実行する場合にはコツが必要
irb(main):001:0> class Cls1 irb(main):002:1> def method1(value) irb(main):003:2> 100 + value irb(main):004:2> end irb(main):005:1> end => :method1 irb(main):006:0> irb(main):007:0* module Mod1 irb(main):008:1> refine Cls1 do irb(main):009:2* def method1 irb(main):010:3> super 50 irb(main):011:3> end irb(main):012:2> end irb(main):013:1> end => #<refinement:Cls1@Mod1> irb(main):014:0> irb(main):015:0* module Mod2 irb(main):016:1> refine Cls1 do irb(main):017:2* def method1 irb(main):018:3> super 100 irb(main):019:3> end irb(main):020:2> end irb(main):021:1> end => #<refinement:Cls1@Mod2> # Refinement でメソッドを追加した場合, 以下のように実行する必要がある irb(main):022:0> using Mod1; using Mod2; puts Cls1.new.method1 200 => nil # もしくは, Refinement でメソッドを追加した場合, 以下のように実行する必要がある irb(main):023:0> begin irb(main):024:1* using Mod1 irb(main):025:1> using Mod2 irb(main):026:1> puts Cls1.new.method1 irb(main):027:1> end 200 => nil
以下, 解説より抜粋.
- 設問では, 同じメソッドに対して Refinement で再定義を2つのモジュールで行っている
using
を 2 行書いても, 1 つのメソッドで有効になる再定義は1つだけとなる為, 最後に書いたusing
から優先される- 有効になる再定義は 1 つなので, モジュール Mod2 にある super はクラス Cls1 の method1 を呼び出す為,
super + 100
は100 + 100
となり200
となる
尚, using Mod1
の内容はすべて無効になったわけではなく, 以下のようなサンプルコードの場合, Mod2 にメソッド method2 が定義されていなくても呼び出すことが出来る.
class Cls1 def method1(value) 100 + value end def method2(value) value + ", world" end end module Mod1 refine Cls1 do def method1 super 50 end def method2 super "Hello" end end end module Mod2 refine Cls1 do def method1 super 100 end end end begin # irb で実行する為 using Mod1 using Mod2 puts Cls1.new.method1 puts Cls1.new.method2 end # irb で実行する為
以下, irb にて確認.
irb(main):001:0> class Cls1 irb(main):002:1> def method1(value) irb(main):003:2> 100 + value irb(main):004:2> end irb(main):005:1> irb(main):006:1* def method2(value) irb(main):007:2> value + ", world" irb(main):008:2> end irb(main):009:1> end => :method2 irb(main):010:0> irb(main):011:0* module Mod1 irb(main):012:1> refine Cls1 do irb(main):013:2* def method1 irb(main):014:3> super 50 irb(main):015:3> end irb(main):016:2> irb(main):017:2* def method2 irb(main):018:3> super "Hello" irb(main):019:3> end irb(main):020:2> end irb(main):021:1> end => #<refinement:Cls1@Mod1> irb(main):022:0> irb(main):023:0* module Mod2 irb(main):024:1> refine Cls1 do irb(main):025:2* def method1 irb(main):026:3> super 100 irb(main):027:3> end irb(main):028:2> end irb(main):029:1> end => #<refinement:Cls1@Mod2> irb(main):030:0> irb(main):031:0* begin # irb で実行する為 irb(main):032:1* using Mod1 irb(main):033:1> using Mod2 irb(main):034:1> puts Cls1.new.method1 irb(main):035:1> puts Cls1.new.method2 irb(main):036:1> end # irb で実行する為 200 Hello, world => nil
確かに. Mod2 には method2 は定義されていないけど, method2 を呼び出すことが出来ている.
フムフム.