使用#include将对象与其自身进行比较时不使用自定义==运算符?

Dan*_*ani 3 ruby equality

用于指定包含关系的文档Array#include?是使用==运算符检查的。我正在使用自定义定义将对象与其自身进行比较的情况下进行检查==

class Foo
  def ==(other)
    false
  end
end

f = Foo.new
f == f # => false 
Run Code Online (Sandbox Code Playgroud)

在这种情况下,文档的描述就不是这种情况了,而另一种机制则优先考虑:

[f].include?(f) # => true
Run Code Online (Sandbox Code Playgroud)

该机制是什么?在哪里定义?

VP.*_*VP. 5

阅读源代码

               VALUE
rb_ary_includes(VALUE ary, VALUE item)
{
    long i;
    VALUE e;

    for (i=0; i<RARRAY_LEN(ary); i++) {
        e = RARRAY_AREF(ary, i);
        switch (rb_equal_opt(e, item)) {
          case Qundef:
            if (rb_equal(e, item)) return Qtrue;
            break;
          case Qtrue:
            return Qtrue;
        }
    }
    return Qfalse;
}
Run Code Online (Sandbox Code Playgroud)

来自https://ruby-doc.org/core-2.2.0/Array.html#method-i-include-3F您将看到ruby没有使用对象运算符

编辑:正如aleksei-matiushkin所说(在评论中), rb_equal_opt(e, item)比较指针并返回true

反转它,您可以用以下方法击中它:

class Foo
  def ==(other)
    puts "yay"
    true
  end
end

> f = Foo.new
=> #<Foo:0x0000000001048610> 
> [f].include?(f)
=> true 
> [f].include?(f.dup)
yay
=> true 

Run Code Online (Sandbox Code Playgroud)

  • 它不使用`#==`运算符仅仅是因为它实际上是同一个对象,并且指针比较会立即返回`true`。如果不是这种情况,`rb_equal`将调用`#==`。最后一个子句“ case Qtrue:return Qtrue;”是返回“ true”的内容。 (4认同)