Singleton methods, Singleton class
Bài đăng này đã không được cập nhật trong 6 năm
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 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
All rights reserved