Sự bằng nhau có nghĩa là hai thứ giống nhau. Trong Ruby, chúng ta so sánh đối tượng và giá trị của chúng để biết chúng có phải cùng đối tượng không.
Câu hỏi là...
Làm sao so sánh hai thứ trong Ruby?
Như thế này:
1 == 1 # true
Bạn có thể đã quen với điều này rồi...
Nhưng bạn có biết == là một phương thức và không chỉ cú pháp?
Hàm ý lớn.
Bạn có thể triển khai phương thức này trong lớp của riêng bạn để làm cho chúng mạnh mẽ hơn. Và đó là điều bạn sẽ học trong bài này!
Điều Gì Làm Hai Đối tượng Giống Nhau?
Bạn có thể so sánh hai chuỗi như thế này:
"foo" == "foo"
Nếu từ và ký tự giống nhau, thì chúng bằng nhau.
Biểu thức trả về true.
Điều này hoạt động vì lớp String triển khai phương thức == (hai dấu bằng) biết cách so sánh chuỗi.
Nhưng nếu String không triển khai == thì sao?
Thì Ruby sẽ dùng triển khai == của Object, mặc định kiểm tra danh tính đối tượng, thay vì nội dung đối tượng.
Ví dụ:
Object.new == Object.new # false String.new == String.new # true
Lý do Object trả về false là vì hai đối tượng mới có object id khác nhau.
Trong trường hợp String, vì nó so sánh dựa trên nội dung, và hai chuỗi mới có cùng nội dung (rỗng), nó trả về true.
Triển khai Sự bằng nhau
Bây giờ hãy dùng những gì bạn vừa học để làm lớp của bạn mạnh mẽ hơn bằng cách có thể so sánh chúng.
Nhờ phương thức ==...
Bạn có thể định nghĩa chính xác điều gì có nghĩa là hai instance của lớp bạn là bằng nhau.
Ví dụ:
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
Phương thức == nói rằng cả tên và giá phải giống nhau để hai đối tượng Product được coi là bằng nhau.
Nhớ:
Nếu bạn không triển khai phương thức này (hoặc dùng module Comparable, tôi giải thích trong sách Ruby của tôi), hai đối tượng sẽ được so sánh dùng object id của chúng, thay vì giá trị.
Cũng tôi nên nhắc nếu bạn dùng Struct, nó đã triển khai == cho bạn.
Còn Triple Equals?
Bạn có thể thắc mắc nếu == là phương thức, === có phải phương thức không? Và câu trả lời là có 🙂
Vậy sự khác biệt giữa hai cái là gì?
Trong Javascript có sự khác biệt rõ ràng, nơi == sẽ thử chuyển đổi kiểu đối tượng để giống nhau nếu chúng không phải (1 vs '1'). Và === cho sự bằng nhau 'nghiêm ngặt'.
Nhưng trong Ruby không có điều đó. Ý nghĩa của === phụ thuộc vào lớp triển khai nó.
Trong nhiều trường hợp, nó chỉ là bí danh cho ==.
Như trong String và Object.
Đây là bảng các lớp tích hợp sẵn cho === ý nghĩa đặc biệt:
| Lớp | Ý nghĩa |
|---|---|
| Range | Trả về true nếu obj là phần tử của range, false ngược lại. |
| Regexp | Khớp regexp với chuỗi. |
| Module | Trả về true nếu obj là instance của mod hoặc instance của một trong các con cháu của mod. |
| Proc | Gọi khối với obj như tham số proc giống Proc#call. Để cho phép đối tượng proc trở thành mục tiêu của mệnh đề when trong câu lệnh case. |
Kết luận
Trong bài này bạn học cách làm lớp của bạn mạnh mẽ hơn bằng cách triển khai phương thức ==. Bạn cũng học sự khác biệt giữa == và ===.
Đừng quên chia sẻ bài viết này để nhiều người hơn thấy nó 🙂