先週、stackoverflow.comで質問に答えたかったのですが、 irbでいくつかのテストを実行した後、興味深いことがわかりました。
class X
def ==(other)
p "X#=="
super
end
end
data = [ 1 ]
data.include?(X.new)
ここでは、配列内のすべてのアイテムArray#include?
が呼び出されることを期待しています。Fixnum#==
したがって、X#==
が呼び出されることはなく、デバッグ メッセージが出力されることもありません。
しかし、実際には私のルビー バージョン (REE 1.8.7、MRI 1.8.7、1.9.2、および 1.9.3) では、X#==
デバッグ メッセージが出力されます。
私がそれをした場合、true
またはfalse
またはnil
またはメッセージをObject.new
出力することはありません。X#==
しかし、次のFixnum#==
ように再定義すると:
class Fixnum
def ==(other)
p "Fixnum#=="
super
end
end
デバッグメッセージを出力した後に実際に元の実装を呼び出すと、出力されFixnum#==
、X#==
最初に期待したように出力されません。
アップデート
干し草の山を針で切り替えると、さらにクレイジーになります。
data = [ X.new ]
data.include?(1)
以前針でメソッドをX#==
呼び出したのにプリントアウトしてしまいます。#==
その背後にある理由を誰か指摘できますか?それとも単に最適化の問題ですか?