在Ruby Koans中,about_open_classes.rb最后的测试是这样的:
class ::Integer
def even?
(self % 2) == 0
end
end
def test_even_existing_built_in_classes_can_be_reopened
assert_equal true, 1.even?
assert_equal false, 2.even?
end
Run Code Online (Sandbox Code Playgroud)
似乎def even?没有做任何事情; 如果我改变方法,它似乎不起作用:
class ::Integer
def even?
(self % 2) != 0
end
end
Run Code Online (Sandbox Code Playgroud)
测试仍然成功.
我认为这是因为even已经在Ruby中定义了.那是对的吗?为什么会这样?
Ruby核心并不特别,问题在于even?这里不是来自Integer它,它来自于Fixnum.而且由于Fixnum其1祖先比整数低,重新定义它Integer没有任何影响,因为从来没有被调用.
重新定义的Fixnum工作正常:
1.even? #=> false
class Fixnum; def even?; true; end end
1.even? #=> true
Run Code Online (Sandbox Code Playgroud)
而且,作为参考,这里1是祖先:
1.class.ancestors #=> [Fixnum, Integer, Numeric, Comparable, Object, Kernel, BasicObject]
Run Code Online (Sandbox Code Playgroud)
你可以告诉even?来自Fixnum通过获取一个Method对象,然后它的owner:
1.method(:even?).owner #=> Fixnum
1.method(:ceil).owner #=> Integer
Run Code Online (Sandbox Code Playgroud)