位置:首页 > Ruby > Ruby四种比较方法区别详解:equal?、eql?、==与===

Ruby四种比较方法区别详解:equal?、eql?、==与===

时间:2026-08-17  |  作者:风起客  |  阅读:0

Ruby 里有四种比较方法:equaleql=====。它们在各个类中的行为差异很大,实际使用时很容易混淆。下面通过几个代码片段,把这几种方法的区别理清楚。

Ruby里4种比较函数(equal?, eql?, ==, ===)详解

== —— 类意义上的相等,由业务逻辑定义

在特定类中,两个对象是否“相同”,取决于业务上的表象。

程序员需要覆盖 == 方法,决定什么样的对象算作相等。

比如 String 类比较的是实际的文字内容,而不在乎是否来自同一块内存区域:

>> a = "abc"
#=> "abc"

>> b = a + ""
#=> "abc"

?> a == b
#=> true

>> a.object_id
#=> 70255156346640

>> b.object_id
#=> 70255156340640

理解重点

  • == 判断的是“逻辑上是否相等”。
  • 是否相等,由类自身的业务逻辑决定。
  • 即使两个对象不是同一个对象,也可能 ==true

=== —— 用于 case 语句的隐式调用

=== 最典型的应用场景,就是 case 条件匹配。

比如:

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

它等价于:

if /a regex/ === some_object
 # The regex matches
elsif String === some_object
 # some_object is kind of object
elsif (2..4) === some_object
 # some_object is in the range 2..4
elsif lambda {|x| some_crazy_custom_predicate } === some_object
 # the lambda returned true
end

理解重点

  • === 主要用于匹配。
  • 它最常见的触发场景是 case
  • 不同类对 === 的实现方式也可能不同。

eql —— 通常意义上的“值相等”

如果两个对象的值相同,eql 返回 true

通常子类在覆盖 == 方法时,会同时 aliaseql

不过有个例外:整数与小数的比较,这两个方法的返回值不同:

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

eql 在 Hash 中的行为

eqlHash 用来比较成员值是否相等。

看这个例子:

[1] pry(main)> hash = Hash.new
#=> {}
[2] pry(main)> hash[2] = "a"
#=> "a"
[3] pry(main)> hash[2.0] = "b"
#=> "b"
[4] pry(main)> hash[2]
#=> "a"
[5] pry(main)> hash[2.0]
#=> "b"
[6] pry(main)> hash[2.00] = "c"
#=> "c"
[7] pry(main)> hash[2.0]
#=> "c"

所以,什么时候需要覆盖 eql

取决于你希望 Hash 在比较键时,依据什么样的规则来判断相等。

理解重点

  • eql 更接近通常意义上的“值相等”。
  • 它常常和 == 保持一致。
  • 但在 Hash 键比较中,它的作用尤其关键。

equal —— 内存地址相同

这个方法不该被子类覆盖。

它比较的是两个对象在内存中是否完全相同,即是否拥有同一个 object_id

看看 Rails 中的例子。即使从数据库取出同一条记录,equal 也返回 false

q = User.first
 User Load (40.4ms) SELECT "users".* FROM "users"  ORDER BY "users"."id" ASC LIMIT 1
#=> #

q2 = User.first
 User Load (0.4ms) SELECT "users".* FROM "users"  ORDER BY "users"."id" ASC LIMIT 1
#=> #

q.equal? q2
#=> false

理解重点

  • equal 只看是不是同一个对象。
  • 它关注的是内存身份,不是业务意义上的相等。
  • 即使内容完全一样,只要不是同一个对象,结果就是 false

记忆方法

  • == —— 按业务需求覆盖,决定“逻辑相等”。
  • === —— 覆盖 case 语句时的匹配逻辑。
  • eql —— 通常 alias==,必要时覆盖它来改变 Hash 比较的表现。
  • equal —— 永远别动它,它只关心内存地址。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多