class << selfkhông chỉ là một cách khai báo các phương thức của lớp (mặc dù nó có thể được sử dụng theo cách đó). Có thể bạn đã thấy một số cách sử dụng như:
class Foo
class << self
def a
print "I could also have been defined as def Foo.a."
end
end
end
Điều này hoạt động, và tương đương với def Foo.a, nhưng cách nó hoạt động hơi tinh tế. Bí mật là self, trong bối cảnh đó, tham chiếu đến đối tượng Foo, có lớp là một lớp con ẩn danh, duy nhất của Class. Lớp con này được gọi là Foo's eigenclass . Vì vậy, def atạo ra một phương pháp mới gọi là atrong Foo's eigenclass, truy cập bằng cú pháp gọi phương thức bình thường: Foo.a.
Bây giờ chúng ta hãy xem xét một ví dụ khác:
str = "abc"
other_str = "def"
class << str
def frob
return self + "d"
end
end
print str.frob
print other_str.frob
Ví dụ này giống với ví dụ cuối cùng, mặc dù ban đầu có thể khó nói. frobđược định nghĩa, không phải trên Stringlớp, mà trên lớp eigenclass của str, một lớp con ẩn danh duy nhất của String. Vì vậy, strcó một frobphương pháp, nhưng các trường hợp Stringnói chung thì không. Chúng tôi cũng có thể có các phương thức được ghi đè của Chuỗi (rất hữu ích trong một số trường hợp thử nghiệm phức tạp).
Bây giờ chúng tôi được trang bị để hiểu ví dụ ban đầu của bạn. FooPhương thức khởi tạo của Inside , selfkhông đề cập đến lớp Foo, mà là một số trường hợp cụ thể của Foo. Eigenclass của nó là một lớp con của Foo, nhưng nó không phải là Foo; nó không thể được, hoặc nếu không thì thủ thuật chúng ta đã thấy trong ví dụ thứ hai không thể hoạt động. Vì vậy, để tiếp tục ví dụ của bạn:
f1 = Foo.new(:weasels)
f2 = Foo.new(:monkeys)
f1.weasels = 4
f2.monkeys = 5
print(f1.monkeys)
Hi vọng điêu nay co ich.