So sánh trong Ruby

I. Giới thiệu

Làm thế nào để ta so sánh giữa 2 đối tượng trong Ruby? Chắc hẳn bạn đã biết phép so sánh == giống như các ngôn ngữ lập trình khác...nhưng bạn có biết == là một phương thức và nó không chỉ là cú pháp thông thường. Bạn có thể xây dựng phương thức này ở trong class của bạn để làm cho nó mạnh mẽ hơn. Và bài này tôi sẽ nói về vấn đề đó.

II. Phép so sánh căn bản

Như bạn biết muốn so sánh 2 string ta làm như sau: "foo" == "foo" Và nếu như nội dung của 2 chuỗi so sánh giống nhau thì phép so sánh trả về true. Phép so sánh ở đây nó hoạt động được với string bởi vì lớp string đã cài đặt phương thức ==, nó hiểu như là để so sánh giữa 2 đối tượng string. Nhưng nếu lớp String không cài đặt phương thức == thì sao? Ruby nên sử dụng phép so sánh == để cài đặt cho đối tượng. Ví dụ:

Object.new == Object.new # false
String.new == String.new # true

III. Cài đặt phép so sánh

Bây giờ hãy học cách làm cho class của bạn mạnh mẽ hơn và có thể so sánh giữa 2 thể hiện của class đó. Nhờ phương thức == bạn có thể định nghĩa chính xác điều gì khi ta so sánh giữa 2 thể hiện của lớp đó. 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 == ở trên có nghĩa là khi mà 2 sản phẩm cùng nameprice giống nhau, phương thức == sẽ trả về true và ngược lại. Chú ý: Nếu bạn không cài đặt phương thức này, mặc định khi ta so sánh giữa 2 thể hiện của 1 lớp, và đã tồn tại trong database, nó sẽ so sánh cả id của 2 thể hiện đó. Và Struct cũng được cài đặt phương thức == cho chúng ta.

IV. Phép so sánh ===

Bạn có thể tự hỏi mình == là phương thức, liệu === nó có phải là một phương thức ? Câu trả lời ở đây là có ! Và sư khác biệt giữa chúng là gì ? Trong javascript, chúng ta có sự khác biệt giữa 2 phương thức này, == sẽ chuyển đổi kiểu cho 2 đối tượng chúng ta so sánh về kiểu giống nhau để so sánh, ví dụ như "1" == 1 sẽ trả về true, còn === sẽ so sánh cả về mặt kiểu dữ liệu của 2 đối tượng đó, ví dụ "1" === 1 sẽ trả về false. Nhưng ở trong ruby, nó không phải là như vậy. Mà === còn phụ thuộc vào lớp mà bạn cài đặt. Trong nhiều trường hợp, nó chỉ là phép thông thường như ==, như ta thực hiện với stringObject. Dưới đây là bảng chỉ ta ý nghĩa đặc biệt của phương thức === phụ thuộc vào hoàn cảnh của chúng ta sử dụng.

Lớp Ý nghĩa
Range Trả về true nếu đối tượng là 1 thành phần của range, false trong trường hợp khác
Regexp So sánh 2 regexp như là chuỗi
Module Trả về true nếu đối tượng là thể hiện của module và thể hiện của module con

V. Tổng kết. Trong bài này tôi chỉ cho bạn cách đơn giản để cho class của bạn mạnh mẽ hơn nhờ thực hiện xây dựng phép so sánh ở trong class đó, và sự khác nhau, giống nhau giữa 2 phép so sánh =====