class << self
- це більше, ніж просто спосіб оголошення методів класу (хоча його можна використовувати і таким чином). Можливо, ви бачили таке вживання, як:
class Foo
class << self
def a
print "I could also have been defined as def Foo.a."
end
end
end
Це працює, і це еквівалентно def Foo.a
, але те, як це працює, є делікатним. Секрет полягає в тому self
, що в цьому контексті посилається на об'єкт Foo
, клас якого є унікальним, анонімним підкласом Class
. Цей підклас називається Foo
«s eigenclass . Таким чином , def a
створюється новий метод , званий a
в Foo
eigenclass «S, доступний за нормальним синтаксису виклику методу: Foo.a
.
А тепер давайте розглянемо інший приклад:
str = "abc"
other_str = "def"
class << str
def frob
return self + "d"
end
end
print str.frob
print other_str.frob
Цей приклад такий самий, як і останній, хоча спочатку це важко сказати. frob
визначається не для String
класу, а для власного класу str
унікального анонімного підкласу String
. Так само str
має frob
метод, але екземпляри String
загалом - ні. Ми могли б також замінити методи String (дуже корисні в певних хитрих сценаріях тестування).
Тепер ми готові зрозуміти ваш оригінальний приклад. Усередині Foo
ініціалізації метод «и, self
відноситься не до класу Foo
, але в якийсь - то конкретної інстанції в Foo
. Його власний клас є підкласом Foo
, але це не так Foo
; цього не могло бути, інакше фокус, який ми побачили у другому прикладі, не міг спрацювати. Отже, щоб продовжити приклад:
f1 = Foo.new(:weasels)
f2 = Foo.new(:monkeys)
f1.weasels = 4
f2.monkeys = 5
print(f1.monkeys)
Сподіваюся, це допомагає.