Spis treściKliknij link, aby przejść do wybranego miejsca
Ta treść została automatycznie przetłumaczona z ukraińskiego.
W Ruby wszystko jest obiektem (no, prawie wszystko), nawet klasy. I każdy obiekt może mieć własne unikalne metody, które nie należą do innych instancji tej samej klasy.
Czym jest Proc i Lambda przeczytaj w moim poprzednim wpisie.
Te metody są przechowywane nie w zwykłej klasie, ale w specjalnej ukrytej klasie, która nazywa się singleton class lub eigenclass.
Czym jest singleton class?
Singleton class to "osobista" klasa konkretnego obiektu. To tam Ruby przechowuje metody, które są zdefiniowane tylko dla tego obiektu.
user1 = "Alice"
user2 = "Bob"
def user1.greet
"Hello, I'm #{self}!"
end
p user1.greet # => "Hello, I'm Alice!"
p user2.greet # => NoMethodError
Tutaj greet to metoda, która istnieje tylko dla obiektu user1. Ruby stworzył dla user1 jego własną singleton class i umieścił tam tę metodę.
Jak zobaczyć singleton_class?
Każdy obiekt ma metodę singleton_class, która pozwala odwołać się do tej "ukrytej" klasy:
user1.singleton_class # => #<Class:#<String:0x0000000103c4b8f0>>
Jeśli zdefiniujesz metodę bezpośrednio w tej klasie - również stanie się unikalna:
user = "Ruby"
user.singleton_class.class_eval do
def version
"3.2.1"
end
end
p user.version # => "3.2.1"
class << self
Kiedy piszesz class << self, w rzeczywistości otwierasz singleton class bieżącego obiektu. To wygodna składnia do definiowania metod wewnątrz niego.
Przykład 1: w zwykłym obiekcie
user = "John"
class << user
def greet
"Hi, I'm #{self}"
end
end
p user.greet # => "Hi, I'm John"
Przykład 2: w klasie (definiowanie metod klasy)
class Person
class << self
def species
"Human"
end
end
end
p Person.species # => "Human"
Ruby po prostu otworzył singleton class dla samej klasy Person i dodał tam metodę species.
Jeśli krótko:
- W Ruby każdy obiekt ma swoją własną singleton class - ukrytą klasę dla jego unikalnych metod.
- Metoda def obj.method lub class << obj dodaje metodę do singleton class tego obiektu.
- Często używasz tego nieświadomie, gdy piszesz metody klasy (class << self) lub unikalne metody dla jednego obiektu.
Ale dla utrwalenia rozważmy pytanie. Czy można wywołać metodę singleton klasy na jej obiekcie? NIE. Nie będzie dostępna na obiekcie klasy (tj. na instancji).
W przykładzie:
class Person
class << self
def species
"Human"
end
end
end
Ruby tworzy metodę klasy, czyli metodę, która żyje w singleton class samej klasy Person, a nie w metodach instancji Person.
Dlatego:
Person.species # => "Human" Person.new.species # => NoMethodError
Wyjaśnienie:
- Person to obiekt klasy Class.
- class << self otwiera singleton class dla tego obiektu (Person).
- Metoda species jest tam przechowywana.
- Instancje Person.new (tworzone obiekty klasy) jej nie widzą, ponieważ szukają metod w zwykłej klasie Person, a nie w jej singleton class.
Jeśli chcesz, aby metoda była dostępna zarówno jako klasowa, jak i instancyjna, możesz po prostu zdefiniować ją dwa razy lub przenieść do modułu:
class Person
def self.species
"Human"
end
def species
"Human"
end
end
Person.species # => "Human"
Person.new.species # => "Human"
Lub bardziej elegancko - przez moduł:
module Species
def species
"Human"
end
end
class Person
extend Species # dodaje metodę jako klasową
include Species # dodaje metodę jako instancyjną
end
Ten post nie ma jeszcze żadnych dodatków od autora.