Ruby裡面有4種比較方法,equal?, eql?, ==, ===,而且在不同的類裡面表現的很不一樣。在使用的時候也特別容易搞糊塗。 這篇博文將示範一些代碼來講解各個方法。
== - 類意義上的 相等,需要每個類自己定義實現
在特定類中覺得兩個對象是否相同,需要看業務上的邏輯表象,所有由程式員覆蓋該方法的定義,決定兩個對象是否相同。
比如 String 類,他是來計較實際的文字串是否相同,而不在意是否來自同一個記憶體地區。
>> a = "abc"#=> "abc">> b = a + ""#=> "abc"?> a == b#=> true>> a.object_id#=> 70255156346640>> b.object_id#=> 70255156340640
=== - 用在 case 語句裡時會調用的方法
通常用在 case 比較調用該方法,比如
case some_objectwhen /a regex/ # The regex matcheswhen String # some_object is kind of Stringwhen 2..4 # some_object is in the range 2..4when lambda {|x| some_crazy_custom_predicate } # the lambda returned trueend
等同於
if /a regex/ === some_object # The regex matcheselsif String === some_object # some_object is kind of objectelsif (2..4) === some_object # some_object is in the range 2..4elsif lambda {|x| some_crazy_custom_predicate } === some_object # the lambda returned trueend
eql? - 通常意義上的 相等
如果兩個對象的值相同將返回 true,如果重新定義了子類的 == 方法,一般需要 alias 到 eql? 方法。 當然也有例外,整數與小數的比較兩個方法的傳回值就不同。
1 == 1.0 #=> true1.eql? 1.0 #=> false
eql? 用在 Hash 裡面用來做成員值比較
[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"
所以什麼時候應該覆蓋這個方法就看你想讓他在 Hash 比較時如何表現。
equal? - 記憶體位址相同的對象
該方法不應該被子類覆蓋
比較的是兩個對象在記憶體中是否相同,是否有同一個object_id值
Rails中及時相同的對象
q = User.first User Load (40.4ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1#=> #<User id: 1, email: "ryan@wongyouth.com">q2 = User.first User Load (0.4ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1#=> #<User id: 1, email: "ryan@wongyouth.com">q.equal? q2#=> false
記憶方法
- == 按業務需求覆蓋該方法
- === 覆蓋 case 語句時的表現
- eql? 別名到 == 方法, 需要時覆蓋方法改變 Hash 比較時的表現
- equal? 不改動