gpt4 book ai didi

ruby - 为什么会调用 "wrong"equal方法呢?

转载 作者:数据小太阳 更新时间:2023-10-29 07:32:24 25 4
gpt4 key购买 nike

上周我想在stackoverflow.com 上回答一个问题,但在 irb 中运行一些测试后,我发现了一件有趣的事情。

class X
def ==(other)
p "X#=="
super
end
end

data = [ 1 ]
data.include?(X.new)

我希望 Array#include? 将对数组中的每个项目调用 Fixnum#==。所以永远不会调用 X#== 并且永远不会打印调试消息。

但实际上在我的 ruby​​ 版本(REE 1.8.7、MRI 1.8.7、1.9.2 和 1.9.3)中,它会打印出 X#== 调试消息。

如果我在 truefalsenil 甚至 Object.new 上这样做,它永远不会打印出来X#== 消息。

但是如果我像这样重新定义 Fixnum#==:

class Fixnum
def ==(other)
p "Fixnum#=="
super
end
end

它实际上在打印调试消息后调用原始实现,它打印出 Fixnum#==X#== 从未像我最初预期的那样打印出来。

更新

当我用针切换干草堆时,它变得更加疯狂:

data = [ X.new ]
data.include?(1)

它打印出 X#==,即使它之前在 needle 上调用了 #== 方法。

谁能指出背后的原因是什么?或者仅仅是一个优化问题?

最佳答案

所以 include? 会将 :== 发送到数组的每个元素。

如果您的元素是truefalsenil,则相等性测试很容易失败,因为只有true==true,等等...

对于Fixnum,不是那么清楚,例如1 == 1.0 # => true。所以 Fixnum#== 将在未知参数的情况下礼貌地颠倒参数的顺序。这将允许您定义自己的“数字”类型。

现在更让你困惑的是,为了理解发生了什么,你重新定义 Fixnum#==。调用 super 不会调用原始方法,而是调用 Object#==。尝试 alias_method_chain(如果在 Ruby 2.0 中,则尝试 prepend!)

顺便说一句,查看实际源代码,Fixnum 将直接处理FixnumBignumFloat。对于其他内置类(例如 RationalComplexBigDecimal)以及用户类,Fixnum#==将反转接收者和参数。我不会相信它为 Rational 做这件事,但所有的实现都会为用户类做这件事。

关于ruby - 为什么会调用 "wrong"equal方法呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15984011/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com