tl; dr:!
在类之外覆盖是一件非常奇怪的事情!有无数种方法可以通过做这样疯狂的事情来“破坏”ruby - 所以你可能会发现玩这些奇怪的想法很有趣,但显然不要在重要的代码中这样做!
在 ruby 中,所有类都继承自顶级基类:BasicObject
. 此类定义顶级对象否定- 即每当您编写
!foo
这实际上是在调用您的对象上调用的方法:!
foo
foo.send(:!)
这使得重新定义特定类的方法成为可能(尽管这是一件非常罕见的事情!) 。例如,在实现空对象模式时,您可以执行以下操作:
class NullObject
def !
true
end
end
my_null = NullObject.new
!!my_null #=> false
(通常,在上面一行中返回的唯一对象是和!)false
nil
false
现在,回到你的例子。你在这里实际上做的是定义一个!
在类上调用的方法Object
(并且没有调用super
来触发原始方法!)。换句话说,您基本上将响应重新定义为一种在内部到处使用的基本方法。某事,某处(??)被这种奇怪的行为弄糊涂了,并且不优雅地失败了。
irb(main):001:0> def !
irb(main):002:1> puts "foo"
irb(main):003:1> super # <-- !! This stops it from breaking completely !!
irb(main):004:1> end
=> :!
irb(main):005:0* method(:!)
foo
foo
=> #<Method: Object#!>
irb(main):006:0> method(:!).source_location
foo
foo
=> ["(irb)", 1]
irb(main):007:0> method(:!).super_method
foo
foo
=> #<Method: BasicObject#!>
以下是您可以重新定义导致奇怪行为/错误的方法的其他一些方法,例如:
def nil?
true
end
# Will now die in weird ways!
class String
def ===(other)
true
end
end
"ruby" === "awesome"
#=> true