class << selfjest czymś więcej niż tylko sposobem deklarowania metod klasowych (chociaż można tego używać w ten sposób). Prawdopodobnie widziałeś takie użycie, jak:
class Foo
class << self
def a
print "I could also have been defined as def Foo.a."
end
end
end
To działa i jest równoważne def Foo.a, ale sposób, w jaki to działa, jest nieco subtelny. Sekret polega na tym self, że w tym kontekście odnosi się do obiektu Foo, którego klasa jest unikalną, anonimową podklasą klasy Class. Podklasa ta nazywana jest Foo„s eigenclass . Tak def atworzy nową metodę zwaną aw Foo„s eigenclass, dostępną przez normalną składnią Sposób połączenia: Foo.a.
Spójrzmy teraz na inny przykład:
str = "abc"
other_str = "def"
class << str
def frob
return self + "d"
end
end
print str.frob
print other_str.frob
Ten przykład jest taki sam jak poprzedni, chociaż na początku może być trudno powiedzieć. frobjest zdefiniowana nie w Stringklasie, ale w klasie własnej str, unikalnej anonimowej podklasie String. strMa więc frobmetodę, ale instancje Stringgeneralnie nie. Mogliśmy również przesłonić metody String (bardzo przydatne w niektórych trudnych scenariuszach testowania).
Teraz jesteśmy przygotowani, aby zrozumieć Twój oryginalny przykład. Wewnątrz Fooinicjuj metoda jest, selfnie odnosi się do grupy Foo, ale w pewnym konkretnym przypadku z Foo. Jego klasa własna jest podklasą Foo, ale tak nie jest Foo; to niemożliwe, bo inaczej sztuczka, którą widzieliśmy w drugim przykładzie, nie zadziałała. Kontynuując przykład:
f1 = Foo.new(:weasels)
f2 = Foo.new(:monkeys)
f1.weasels = 4
f2.monkeys = 5
print(f1.monkeys)
Mam nadzieję że to pomoże.