LoginSignup
0
0

More than 5 years have passed since last update.

Ruby 1.8 と 1.9 以降で delegator の挙動が変わっている

Last updated at Posted at 2013-11-22

Evaluating Alternative Decorator Implementations In Ruby
これの最後の delegate を使ったサンプルが Ruby 1.8 だと素直に動かなかった。

Ruby の delegate ライブラリについてはとりあえずここを読めば分かると思う。
Rubyist Magazine - 標準添付ライブラリ紹介 【第 6 回】 委譲

問題

test_delegator.rb
class Coffee
  def cost
    2
  end
end

require 'delegate'

class Decorator < SimpleDelegator
  def class
    __getobj__.class
  end
end

class Milk < Decorator
  def cost
    super + 0.4
  end
end

coffee = Coffee.new
puts Milk.new(coffee).cost
irb(main):001:0> RUBY_VERSION
=> "1.8.7"
irb(main):002:0> load 'test_delegator.rb'
2
irb(main):001:0> RUBY_VERSION
=> "1.9.3"
irb(main):002:0> load 'test_delegator.rb'
2.4

最後の結果が違うのに注目すれば良いのだけど、要点は

  • (Simple)Delegator を継承したクラス(この場合は Decorator)で class メソッドを __getobj__.class とオーバーライドした場合
  • 移譲先オブジェクトのメソッドをオーバーライド(Milk#cost)しても、Ruby 1.8 だとオーバーライドがうまく動作しない

という感じ。

ソースを追ったら Delegator クラスの initialize の中で self.class.ancestors のメソッドを再定義しているのがダメっぽい。
1.9 からは別実装になってるので、問題無く動作する。

解決策

力技だけど、1.9 のソースを持ってきて、1.8 以下の時はそっちを使うようにした。

もっと良い解決策

Ruby のバージョンをあげる

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0