ruby – 为什么称它为“错误的”平等方法?
上周我想在
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执行此操作的事实,但所有实现都将为用户类执行此操作. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |