+2

Ruby's Singleton class là gì? Cách hoạt động của class method trong ruby

Mối quan hệ giữa class và singleton class

Bài viết dựa theo trang Module#extend: Understanding Ruby Singleton Classes của Jem Zornow

Nếu bạn đã học lập trình hướng đối tượng từ những ngôn ngữ như C ++ hoặc Java thì khi bạn chuyển sang Ruby, bạn sẽ cảm thấy có những thứ của Ruby có vẻ "ảo" và khó hiểu. Sau khi chạy theo cú pháp dành riêng cho meta-programming, bạn bắt đầu gãi đầu (do đầu nhiều gàu) hoặc ít nhất là tự hỏi: "Cái éo gì đang diễn ra vậy?". Và Singleton class (không phải singleton pattern đâu nhá), có thể dễ dàng được đặt vào danh mục "gãi đầu" này.

Bản thân cái tên Singleton class rất khó hiểu, nó hay gây nhầm lẫn cho mọi người và dẫn đến việc chúng ta phải tạo một cái tên thay thế khác, chẳng hạn như: object-specific classes, anonymous classes, virtual classes hoặc eigenclasses. Mình hay gọi nó là anonymous classes nhưng thôi vì ích nước lợi nhà mình sẽ dùng cụm từ singleton classes cho dễ hiểu nhé.

Method Dispatching

Trước khi chúng ta tìm hiểu về singleton classes, hãy tìm hiểu về dynamic dispatch:

Với mỗi method được "gọi" (call), trình thông dịch Ruby cần kiểm tra hệ thống phân cấp kế thừa của "người nhận" (receiver) để tìm meothd sẽ được thực thi.

Mình sẽ hỏi bạn: Các phương thức (methods) được định nghĩa ở đâu?

Nếu bạn trả lời: "Dễ ẹt, ở class" thì bạn chỉ trả lời đúng một nửa. Ruby's classes chỉ định nghĩa instance methods, cái mà các bạn hay sử dụng đối với các biến instance variable đó:

class Employee
  def validate_id!
    puts "Checking...."
  end
end

some_employee = Employee.new
some_employee.validate_id!

# => "Checkingv..."

Nó gọi như thế nào?

Hãy xem xét một ví dụ của class Employee:

instace variable some_employee không biết rằng nó có một method. Nó chỉ biết nó là 1 member của class Employee. Khi bạn gọi 1 method từ some_employee, Ruby lần theo class mà nó trỏ đến và tìm method phù hợp trong class đó.

Một cách khá là hay để tiết kiệm bộ nhớ, theo cách đó, các instance của mỗi lớp không cần mang theo các bản sao của mọi phương thức cá thể mà chúng trả lời. Nó là một cách tốt để tiết kiệm bộ nhớ trong hệ thống.

Class Methods —  Nà ní !!

Bạn có bao giờ để ý chỉ có Module#instance_methods mà không có Module#class_methods không? Theo mình thì nó nằm trong chuyên mục gãi đầu rùi đấy 😃

Trong bài viết Module#extend: Understanding Ruby Singleton Classes của Jem Zornow, ổng có nói rằng:

There is no such thing as a Ruby class method, only instance methods that look and smell like class methods.

Khi chúng ta định nghĩa lại validate_id! là class method:

class Employee
  def self.validate_id!
    puts "Checking...."
  end
end

Employee.validate_id!
# => "Checkingv..."

Ruby sẽ chạy theo cái luồng giống như cái ta đã làm trước kia:

Chúng ta sẽ kiểm tra lớp Employee cho instance method. Nếu không tìm thấy nó, chúng ta sẽ theo con trỏ đó tham chiếu đến lớp Class và tìm nó ở đó. Employee, xét cho cùng, là một instance của lớp Class.

Nhưng chờ đã. Nếu chúng ta tìm thấy validate_id! trên lớp Class, thì phương thức đó sẽ có sẵn cho mọi lớp, không chỉ Employee ( Lại một cái gãi đầu nữa?)

Ruby Singleton Classes

Singleton class is the class which hold singleton methods and class methods of specific-object (or specific-class)

Bạn có thể thấy một đoạn code như thế này trước đây:

some_employee = Employee.new

def some_employee.new_method
  puts "This is me"
end

Chúng ta sẽ gọi new_method là một singleton method của một instance: some_employee. Object chứa phương thức đó (some_employee) sẽ được gọi là singleton class. Hãy thử:

clas Employee; end
some_employee = Employee.new

def some_employee.new_method
  puts "This is me"
end

some_employee.singleton_class.instance_methods.include?(:new_method)
# => true

some_employee.class.instance_methods.include?(:new_method)
# => false

Nếu việc định nghĩa phương thức ở bên lớp Employee, vậy instance method new_method đó sẽ mất đi.

Chốt lại: WTF is Class Method?

Có 2 cách trả lời: Cách 1: Class method là các method được định nghĩa bên trong class đó.

Cách 2: Class method là cách method được định nghĩa bên trong một singleton class của class đó 😃

Các bạn cứ hiểu như này nè:

# Class method: các method được định nghĩa bên trong class đó.
class ThisIsMe
  def ThisIsMe.call_me_baby
    puts "9.pm at Quat-Lam's hotel"
  end
end

ThisIsMe.call_me_baby
# => 9.pm at Quat-Lam's hotel



#  Class method: các method được định nghĩa bên trong một singleton class của class đó :)
class ThisIsMe; end
def ThisIsMe.call_me_baby
  puts "9.pm at Quat-Lam's hotel"
end

ThisIsMe.call_me_baby
# => 9.pm at Quat-Lam's hotel

Vì bài của ông thần Jem Zornow gì gì đó rất là khủng, những đứa nghiệp dư như mình có nội công ít, khó mà có thể hiểu được cảnh giới của vị cao nhân kia, cho nên là "chưa hiểu ý tác giả". Nếu các bạn thấy bài viết (bài dịch đúng hơn) còn chỗ nào sai sót, hoặc sai kiến thức, hệ thống, mong các bạn chỉ giảo ạ.

À còn một việc nữa:

Có 2 loại singleton class trong ruby mà các bạn phải để ý:

class ThisIsMe; end

# Singleton class này sử dụng để lưu các class method của lớp ThisIsMe
puts ThisIsMe.singleton_class

# Singleton class này sử dụng để lưu các singleton method của object ThisIsMe.new
puts ThisIsMe.new.singleton_class

Cảm ơn các bạn đã đọc đến đây. Xin cảm ơn!!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí