加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 为什么称它为“错误的”平等方法?

发布时间:2020-12-17 02:34:17 所属栏目:百科 来源:网络整理
导读:上周我想在 stackoverflow.com回答一个问题,但在用irb运行一些测试之后我发现了一件有趣的事情. class X def ==(other) p "X#==" super endenddata = [ 1 ]data.include?(X.new) 我期待这里的数字#include?将在数组中的每个项目上调用Fixnum#==.因此永远不
上周我想在 stackoverflow.com回答一个问题,但在用irb运行一些测试之后我发现了一件有趣的事情.

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

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

我期待这里的数字#include?将在数组中的每个项目上调用Fixnum#==.因此永远不会调用X#==并且永远不会打印调试消息.

但实际上在我的ruby版本(REE 1.8.7,MRI 1.8.7,1.9.2和1.9.3)中,它打印出X#== debug消息.

如果我在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#==,即使它之前在针上调用了#==方法.

任何人都可以指出背后的原因是什么?或者只是一个优化问题?

解决方法

那么包括?将发送:==到您的数组的每个元素.

如果你的元素是true,false和nil,那么相等测试很容易失败,因为只有true是==到true等等……

对于Fixnums,它不是那么清楚,例如1 == 1.0#=>真正.因此Fixnum#==在未知参数的情况下会礼貌并且反转参数的顺序.这将允许您定义自己的“数字”类型.

现在让你感到困惑的是,为了理解发生了什么,你重新定义了Fixnum#==.调用super不会调用原始方法,而是调用Object#==.尝试alias_method_chain(或者在Ruby 2.0中预先添加!)

顺便说一句,看看实际来源,Fixnum将直接处理Fixnum,Bignum和Float.对于其他内置类(例如Rational,Complex,BigDecimal)以及用户类,Fixnum#==将反转接收器和参数.我不会依赖于它为Rational执行此操作的事实,但所有实现都将为用户类执行此操作.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读