相等性意味著兩件事是一樣的。在 Ruby,我們比較物件和它們的值來發現它們是否為同一個物件。
問題是……
如何在 Ruby 比較兩件事?
像這樣:
1 == 1 # true
你可能已經熟悉這個……
但你知道 == 是個方法,不只是語法嗎?
含意很大。
你可以在自己的類別實作這個方法讓它們更強大。這就是你在這篇文章將學到的!
什麼讓兩個物件相同?
你可以這樣比較兩個字串:
"foo" == "foo"
如果 單字和字元 相同,它們就相等。
運算式回傳 true。
這能動是因為 String 類別實作了 ==(兩個等號)方法,知道如何比較字串。
但如果 String 沒實作 == 呢?
那麼 Ruby 會用 Object 的 == 實作,預設測試物件身分,而不是物件內容。
例子:
Object.new == Object.new # false String.new == String.new # true
Object 回傳 false 的原因是兩個新物件有不同的 object id。
對於 String,因為它基於內容比較,兩個新字串內容相同(都是空的)所以回傳 true。
實作相等性
現在用你剛學到的讓你自己的類別更強大,能夠比較它們。
多虧了 == 方法……
你可以精確定義兩個你自己類別的實例何時相等。
例子:
class Product attr_reader :name, :price def initialize(name, price) @name, @price = name, price end def ==(other) self.name == other.name && self.price == other.price end end p1 = Product.new('book', 49) p2 = Product.new('book', 49) p1 == p2 # true == 方法說名稱和價格都必須相同,兩個 Product 物件才視為相等。
記住:
如果你不實作這方法(或用 Comparable 模組,我在我的 Ruby 書解釋)兩個物件會用它們的 object id 比較,而不是值。
也應該提到如果你用 Struct 它已經幫你實作 == 了。
那三個等號 (===) 呢?
你可能想既然 == 是方法,=== 也是方法嗎?答案是 yes 🙂
那麼兩者差別是什麼?
在 Javascript 有明確差別,== 會嘗試轉換物件類型使其相同如果不一樣(1 vs '1')。而 === 是「嚴格」相等。
但在 Ruby 沒有這種事。=== 意思取決於實作它的類別。
在許多情況下它只是 == 的別名。
像在 String 和 Object。
這裡有內建類別給 === 特殊含義的表格:
| Class | Meaning |
|---|---|
| Range | 如果 obj 是 range 的元素回傳 true,否則 false。 |
| Regexp | 對字串比對 regexp。 |
| Module | 如果 obj 是 mod 的實例或 mod 後代的實例回傳 true。 |
| Proc | 用 obj 作為 proc 參數調用區塊,像 Proc#call。允許 proc 物件成為 case 陳述式 when 子句的目標。 |
結論
這篇文章你學到如何實作 == 方法讓類別更強大。也學到 == 和 === 的差別。
別忘了 分享這篇文章 讓更多人看到 🙂