ようへいの日々精進XP

よかろうもん

2018 年 06 月 22 日 (金)

ジョギング

  • 自宅→香椎神宮香椎浜 で 31 分くらい
  • 引き続き, 右腰, 右臀部の強い張り (ストレッチでなんとかしている)
  • 引き続き, 左足足底筋にも違和感あり
  • 暑くなってキタ━━━━(゚∀゚)━━━━!!

日課

  • (腕立て 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 + 100100 + 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 を呼び出すことが出来ている.

フムフム.