小编典典

equal?、eql?、=== 和 == 有什么区别?

all

我试图了解这四种方法之间的区别。我知道默认情况下,当两个操作数都引用完全相同的对象时,它会==调用返回 true 的方法。equal?

===默认情况下还会调用==which call equal?… 好吧,所以如果所有这三个方法都没有被覆盖,那么我猜
=====并且equal?做同样的事情?

现在来了eql?。这是做什么的(默认情况下)?它会调用操作数的哈希/ID吗?

为什么 Ruby 有这么多等号?他们应该在语义上有所不同吗?


阅读 109

收藏
2022-03-07

共1个答案

小编典典

我将在这里大量引用Object 文档,因为我认为它有一些很好的解释。我鼓励您阅读它,以及这些方法的文档,因为它们在其他类中被覆盖,例如String

旁注:如果您想在不同的对象上自己尝试这些,请使用以下内容:

class Object
  def all_equals(o)
    ops = [:==, :===, :eql?, :equal?]
    Hash[ops.map(&:to_s).zip(ops.map {|s| send(s, o) })]
  end
end

"a".all_equals "a" # => {"=="=>true, "==="=>true, "eql?"=>true, "equal?"=>false}

==——一般的“平等”

在对象级别,仅当和是同一个对象==时才返回 true 。通常,此方法在后代类中被覆盖以提供特定于类的含义。obj``other

这是最常见的比较,因此是您(作为类的作者)决定两个对象是否“相等”的最基本的地方。

===∥ 大小写相等

对于类 Object,实际上与 call 相同#==,但通常被后代覆盖以在 case 语句中提供有意义的语义。

这非常有用。具有有趣===实现的事物示例:

  • 范围
  • 正则表达式
  • 过程(在 Ruby 1.9 中)

因此,您可以执行以下操作:

case some_object
when /a regex/
  # The regex matches
when 2..4
  # some_object is in the range 2..4
when lambda {|x| some_crazy_custom_predicate }
  # the lambda returned true
end

通过提供您自己的实现,您可以获得自定义语义。case``Regex``===``case

eql?``Hash——平等

如果和引用相同的哈希键,该eql?方法返回 true 。这用于测试成员是否相等。 对于类的对象 是 的同义词
子类通常通过为其覆盖的方法起别名来延续这一传统,但也有例外。例如,types 执行类型转换 across ,而不是 across
,所以:obj``other``Hash Object``eql?``==eql?``==``Numeric``==``eql?

1 == 1.0     #=> true
1.eql? 1.0   #=> false

因此,您可以自由地覆盖它以供自己使用,或者您可以覆盖==并使用alias :eql? :==,因此这两种方法的行为方式相同。

equal?——身份比较

与 不同==的是,该equal?方法永远不应该被子类覆盖:它用于确定对象身份(即a.equal?(b)iffa是与 相同的对象b)。

这实际上是指针比较。

2022-03-07