Singleton methods, Singleton class
Lớp ẩn danh Cùng xem ví dụ sau: foo = String . new foo . class # String foo . length # 0 foo . bar # NoMethodError Ở đây ta tạo một đối tượng foo thuộc lớp String, và gọi phương thức length của lớp String ra. Với foo.bar thì trình thông dịch của ruby không tìm ...
Lớp ẩn danh
Cùng xem ví dụ sau:
foo = String.new foo.class # String foo.length # 0 foo.bar # NoMethodError
Ở đây ta tạo một đối tượng foo thuộc lớp String, và gọi phương thức length của lớp String ra. Với foo.bar thì trình thông dịch của ruby không tìm thấy phương thức này lên báo lỗi NoMethodError.
Ta xem tiếp ví dụ sau:
foo = String.new def foo.bar puts "xin chao!" end foo.bar # "xin chao!"
Ở đây ruby đã tìm thấy phương thức bar và trả về giá trị. Nhưng câu hỏi đặt ra là phương thức bar này là của lớp nào? Là của lớp String hay một lớp tên là foo?
Đầu tiên để xem một method có thuộc một lớp không ta có thể thử cách sau:
String.instance_methods.include? :length => true
Thử với phương thức bar:
String.instance_methods.include? :bar => false foo.instance_methods.include? :bar => undefined method `instance_methods'
Đối với phương án một lớp tên foo thậm chí còn bị lỗi NoMethodError với chính hàm instance_methods, vì vậy foo không phải là tên lớp, nó vẫn là một biến String. Vậy phương thức bar của chúng ta ở đâu ra, câu trả lời theo mình chính là ở một lớp ẩn danh hay Ruby còn gọi là Singleton Class.
Singleton Class & Singleton Method
Singleton Class, eigen class, anonymous class. là một trong những cách mà ta có thể gọi nó. Thử với ví dụ trước xem nào:
foo.singleton_class.instance_methods.include? :bar => true
Vậy là ta đã biết phương thức bar của chúng ta nằm ở đâu, nó nằm ở Singleton Class của đối tượng foo. Và bar được gọi là một Singleton Method.
Singleton class không có tên, không thể khởi tạo đối tượng mới từ nó. Nó chỉ xuất hiện khi bạn tạo các singleton method, và ruby sẽ tạo các singleton class như một cách để chứa các singleton method, và kế thừa lớp của đối tượng mà bạn tạo singleton method.
Một số cách để tạo singleton method
Với module
module Cin def cin "Tam biet!" end end foo = String.new foo.extend Cin foo.cin => "Tam biet!"
Mở singleton class
foo = String.new class << foo def cin "Tam biet!" end end foo.cin => "Tam biet!"
Đặt tên trực tiếp
Đây chính là cách ta làm ở phần 1
foo = String.new def foo.cin "Tam biet!" end foo.cin => "Tam biet!"
Sử dụng singleton method như thế nào?
Mình cũng chưa nghĩ ra được nhiều cách ứng dụng, nhưng dễ thấy nhất là các class method mà chúng ta hay sử dụng.
Class Method
Class sinhvien def sinhvien.all all end # hoặc Class << self def all all end end end
Test với private method
class Sinhvien attr_accessor :name def initialize name @name = name end def downcase? name_downcase? end private def name_downcase? @name == @name.downcase end end sv1 = Sinhvien.new "hung" sv2 = Sinhvien.new "Hung" def Sinhvien.test_name_downcase? name name == name.downcase end p Sinhvien.test_name_downcase? sv1.name => true p Sinhvien.test_name_downcase? sv2.name => false p sv1.downcase? => true p sv2.downcase? => false