ようへいの日々精進XP

よかろうもん

2018 年 07 月 02 日 (月)

ジョギング

日課

  • (腕立て x 50 + 腹筋 x 50) x 3

体調不良

  • 終日眠気と体のだるさで辛かった

今日のるびぃ ~ だいぶん古いけど, 「Ruby 2.0 最速入門」という記事を写経する (1) ~

だいぶん古い WEB+DB Press Vol.73 の「一歩先ゆく Ruby」というコーナーで「Ruby 2.0 最速入門」という記事が試験にあたって参考になりそうだったので写経する. 尚, irb に動作確認環境は以下の通り.

$ ruby --version
ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-linux]
$ irb --version
irb 0.9.6(09/06/30)

include と prepend

メソッド探索の基本

以下のようなコードがあったとする.

class Mammal
  def have_backbone?
    true
  end

  def live_in_water?
    false
  end
end

class Dog < Mammal
end

上記の場合, Dog インスタンスを作成すると, Mammal を継承している為,

  • have_backbone? は true
  • live_in_water? は false

となる. 以下, irb にて確認した例.

irb(main):014:0> class Mammal
irb(main):015:1>   def have_backbone?
irb(main):016:2>     true
irb(main):017:2>   end
irb(main):018:1> 
irb(main):019:1*   def live_in_water?
irb(main):020:2>     false
irb(main):021:2>   end
irb(main):022:1> end
=> :live_in_water?
irb(main):023:0> 
irb(main):024:0* class Dog < Mammal
irb(main):025:1> end
=> nil
irb(main):030:0> Dog.new.have_backbone?
=> true
irb(main):031:0> Dog.new.live_in_water?
=> false

include

Dolphin というクラスの場合, live_in_water? では true を返したいので Mammal クラスの実装では問題がある為, Swimmable モジュールを利用する.

module Swimmable
  def live_in_water?
    true
  end
end

class Dolphin < Mammal
  def live_in_water?
    super
  end
  include Swimmable
end

以下, irb にて確認.

irb(main):032:0> module Swimmable
irb(main):033:1>   def live_in_water?
irb(main):034:2>     true
irb(main):035:2>   end
irb(main):036:1> end
=> :live_in_water?
irb(main):037:0> 
irb(main):038:0* class Dolphin < Mammal
irb(main):039:1>   include Swimmable
irb(main):040:1> end
=> Dolphin
irb(main):041:0> Dolphin.new.have_backbone?
=> true
irb(main):042:0> Dolphin.new.live_in_water?
=> true

メソッドは以下のような順番で探索される.

  1. Dolphin クラスのインスタンスメソッド
  2. Swimmable モジュールのメソッド
  3. Mammal クラスのインスタンスメソッド

prepend

colors というメソッドを定義した場合.

class Dolphin < Mammal
  def colors
    ['Gray']
  end
end

以下, irb にて確認.

irb(main):067:0> class Dolphin < Mammal
irb(main):068:1>   def colors
irb(main):069:2>     ['Gray']
irb(main):070:2>   end
irb(main):071:1> end
=> :colors
irb(main):072:0> Dolphin.new.colors
=> ["Gray"]

白いイルカが発見された場合, 以下のようにモンキーパッチを適用することで対応出来る.

class Dolphin < Mammal
  def colors
    ['White', 'Gray']
  end
end

以下, irb にて確認.

irb(main):073:0> class Dolphin < Mammal
irb(main):074:1>   def colors
irb(main):075:2>     ['White', 'Gray']
irb(main):076:2>   end
irb(main):077:1> end
=> :colors
irb(main):078:0> Dolphin.new.colors
=> ["White", "Gray"]

モンキーパッチではなく, 別途モジュールを用意して prepend を利用して解決する.

module WithColorWhite
  def colors
    ['White'] + super
  end
end

class Dolphin < Mammal
  prepend WithColorWhite
end

以下, irb にて確認.

irb(main):079:0> class Dolphin < Mammal
irb(main):080:1>   def colors
irb(main):081:2>     ['Gray']
irb(main):082:2>   end
irb(main):083:1> end
=> :colors
irb(main):084:0> Dolphin.new.colors
=> ["Gray"]
irb(main):085:0> module WithColorWhite
irb(main):086:1>   def colors
irb(main):087:2>     ['White'] + super
irb(main):088:2>   end
irb(main):089:1> end
=> :colors
irb(main):090:0> class Dolphin < Mammal
irb(main):091:1>   prepend WithColorWhite
irb(main):092:1> end
=> Dolphin
irb(main):093:0> Dolphin.new.colors
=> ["White", "Gray"]

prepend を利用した場合, メソッドは以下のような順番で探索され, Dolphin クラスで定義されている colors メソッドを super で参照出来る.

  1. WithColorWhite モジュールのメソッド
  2. Dolphin クラスのインスタンスメソッド
  3. Swimmable モジュールのメソッド
  4. Mammal クラスのインスタンスメソッド

フムフム.