Co ma class << self
zrobić w Ruby ?
Co ma class << self
zrobić w Ruby ?
Odpowiedzi:
Po pierwsze, class << foo
składnia otwiera foo
klasę singleton (eigenclass). Pozwala to na specjalizację zachowania metod wywoływanych na tym konkretnym obiekcie.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
Teraz, aby odpowiedzieć na pytanie: class << self
otwiera self
singletonową klasę, dzięki czemu można przedefiniować metody dla bieżącego self
obiektu (który wewnątrz ciała klasy lub modułu jest samą klasą lub modułem ). Zwykle służy to do definiowania metod klasy / modułu („statycznych”):
class String
class << self
def value_of obj
obj.to_s
end
end
end
String.value_of 42 # => "42"
Można to również zapisać jako skrót:
class String
def self.value_of obj
obj.to_s
end
end
Lub nawet krócej:
def String.value_of obj
obj.to_s
end
Znajdując się w definicji funkcji, self
odnosi się do obiektu, za pomocą którego funkcja jest wywoływana. W takim przypadku class << self
otwiera klasę singleton dla tego obiektu; jednym z nich jest zaimplementowanie automatu stanów biednego człowieka:
class StateMachineExample
def process obj
process_hook obj
end
private
def process_state_1 obj
# ...
class << self
alias process_hook process_state_2
end
end
def process_state_2 obj
# ...
class << self
alias process_hook process_state_1
end
end
# Set up initial state
alias process_hook process_state_1
end
Tak więc w powyższym przykładzie każde wystąpienie aliasu StateMachineExample
zostało process_hook
przypisane do aliasu process_state_1
, ale zwróć uwagę na to, jak w tym drugim przypadku może ono przedefiniować process_hook
( self
tylko nie wpływając na inne StateMachineExample
wystąpienia) na process_state_2
. Tak więc, za każdym razem, gdy wywołujący wywołuje process
metodę (która wywołuje funkcję redefiniowalną process_hook
), zachowanie zmienia się w zależności od tego, w jakim jest stanie.
class << self
tworzenia klas / modułów. Prawdopodobnie rozwinę to zastosowanie class << self
, ponieważ jest to o wiele bardziej idiomatyczne zastosowanie.
a
„s singleton_class
od a
” s klasy (po zmianie inspect
) to unikalny wariant String
klasy. Gdyby zmienił String
klasę singletonów , wpłynęłoby to na wszystkie inne String
instancje. Dziwniejsze jest to, że jeśli później ponownie otworzysz, String
aby ponownie zdefiniować, inspect
to a
nadal wybierzesz nowe zmiany.
class << self
oznacza, że cokolwiek więcej niż wartość self
jest równa klasie singletonu w zakresie bloku?
Znalazłem super proste wyjaśnienie class << self
, Eigenclass
oraz różnego rodzaju metod.
W Ruby istnieją trzy typy metod, które można zastosować do klasy:
Metody instancji i metody klas są prawie podobne do ich homonimów w innych językach programowania.
class Foo
def an_instance_method
puts "I am an instance method"
end
def self.a_class_method
puts "I am a class method"
end
end
foo = Foo.new
def foo.a_singleton_method
puts "I am a singletone method"
end
Innym sposobem uzyskania dostępu do Eigenclass
(który obejmuje metody singleton) jest następująca składnia ( class <<
):
foo = Foo.new
class << foo
def a_singleton_method
puts "I am a singleton method"
end
end
teraz możesz zdefiniować metodę singleton, dla self
której Foo
sama klasa jest w tym kontekście:
class Foo
class << self
def a_singleton_and_class_method
puts "I am a singleton method for self and a class method for Foo"
end
end
end
foo.singleton_class.instance_methods(false)
do sprawdzenia.
Zazwyczaj metody instancji są metodami globalnymi. Oznacza to, że są dostępne we wszystkich instancjach klasy, w której zostały zdefiniowane. Natomiast metoda singletonu jest implementowana na jednym obiekcie.
Ruby przechowuje metody w klasach i wszystkie metody muszą być powiązane z klasą. Obiekt, w którym zdefiniowana jest metoda singleton, nie jest klasą (jest instancją klasy). Jeśli tylko klasy mogą przechowywać metody, w jaki sposób obiekt może przechowywać metodę singleton? Kiedy tworzona jest metoda singleton, Ruby automatycznie tworzy anonimową klasę do przechowywania tej metody. Te anonimowe klasy nazywane są metaklasami, znanymi również jako klasy singleton lub klasy eigenclasses. Metoda singletonu jest powiązana z metaklasą, która z kolei jest powiązana z obiektem, na którym zdefiniowano metodę singletonu.
Jeśli w jednym obiekcie zdefiniowano wiele metod singletonów, wszystkie są przechowywane w tej samej metaklasie.
class Zen
end
z1 = Zen.new
z2 = Zen.new
class << z1
def say_hello
puts "Hello!"
end
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
W powyższym przykładzie klasa << z1 zmienia bieżące „ja”, aby wskazywało metaklasę obiektu z1; następnie definiuje metodę say_hello w metaklasie.
Klasy są również obiektami (instancjami wbudowanej klasy o nazwie Class). Metody klasy są niczym więcej niż metodami singletonowymi powiązanymi z obiektem klasy.
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
Wszystkie obiekty mogą mieć metaklasy. Oznacza to, że klasy mogą mieć także metaklasy. W powyższym przykładzie klasa << self modyfikuje self, więc wskazuje na metaklasę klasy Zabuton. Kiedy metoda jest zdefiniowana bez jawnego odbiornika (klasy / obiektu, na którym metoda zostanie zdefiniowana), jest ona domyślnie zdefiniowana w ramach bieżącego zakresu, to znaczy bieżącej wartości self. Dlatego metoda rzeczy jest zdefiniowana w metaklasie klasy Zabuton. Powyższy przykład jest tylko innym sposobem zdefiniowania metody klasy. IMHO, lepiej jest użyć składni def self.my_new_clas_method do zdefiniowania metod klas, ponieważ ułatwia to zrozumienie kodu. Powyższy przykład został dołączony, abyśmy rozumieli, co się dzieje, gdy natrafimy na składnię << siebie składni klasy.
Dodatkowe informacje można znaleźć w tym poście na temat klas Ruby .
class Hi
self #=> Hi
class << self #same as 'class << Hi'
self #=> #<Class:Hi>
self == Hi.singleton_class #=> true
end
end
[robi self == thing.singleton_class
w kontekście swojego bloku] .
hi = String.new
def hi.a
end
hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true
hi
obiekt dziedziczy #methods
po nim, #singleton_class.instance_methods
a następnie po nim #class.instance_methods
.
Tutaj daliśmy hi
„s singleton klasy metody instancji :a
. Można to zrobić za pomocą klasy << hi zamiast tego.
hi
„S #singleton_class
ma wszystkie metody instancji hi
” S #class
ma, ewentualnie nieco więcej ( :a
o).
[instancyjne metody rzeczy #class
i #singleton_class
mogą być stosowane bezpośrednio do rzeczy. kiedy Ruby widzi rzecz. a, najpierw szuka: definicji metody w thing.singleton_class.instance_methods, a następnie w thing.class.instance_methods]
Nawiasem mówiąc - nazywają obiektu Singleton klasy == metaklasa == eigenclass .
Á sposób Singleton jest sposób, który jest zdefiniowany jedynie na pojedynczy obiekt.
Przykład:
class SomeClass
class << self
def test
end
end
end
test_obj = SomeClass.new
def test_obj.test_2
end
class << test_obj
def test_3
end
end
puts "Singleton's methods of SomeClass"
puts SomeClass.singleton_methods
puts '------------------------------------------'
puts "Singleton's methods of test_obj"
puts test_obj.singleton_methods
Metody Singletona w SomeClass
test
Metody singletona z test_obj
test_2
test_3
W rzeczywistości, jeśli napiszesz jakieś rozszerzenia C dla swoich projektów Ruby, jest tak naprawdę tylko jeden sposób na zdefiniowanie metody Module.
rb_define_singleton_method
Wiem, że ten własny biznes po prostu otwiera wiele innych pytań, dzięki czemu możesz lepiej przeszukać każdą część.
Przede wszystkim obiekty.
foo = Object.new
Czy mogę stworzyć metodę foo?
Pewnie
def foo.hello
'hello'
end
Co mam z tym zrobić?
foo.hello
==>"hello"
Po prostu kolejny przedmiot.
foo.methods
Otrzymasz wszystkie metody Object plus swoją nową.
def foo.self
self
end
foo.self
Tylko obiekt foo.
Spróbuj zobaczyć, co się stanie, jeśli zrobisz foo z innych obiektów, takich jak klasa i moduł. Przykłady wszystkich odpowiedzi są fajne, ale musisz pracować z różnymi pomysłami lub koncepcjami, aby naprawdę zrozumieć, co się dzieje ze sposobem pisania kodu. Masz teraz wiele warunków do obejrzenia.
Wychowano Singleton, Class, Module, self, Object i Eigenclass, ale Ruby nie nazywa w ten sposób Modelów Obiektów. To bardziej jak Metaklasa. Richard lub __why pokazuje ci ten pomysł tutaj. http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html A jeśli cię to zaskoczy, spróbuj poszukać Ruby Object Model w poszukiwaniu. Dwa filmy, które znam na YouTube to Dave Thomas i Peter Cooper. Próbują również wyjaśnić tę koncepcję. Zdobycie go zajęło Dave'owi dużo czasu, więc nie martw się. Nadal nad tym pracuję. Po co miałbym tu być? Dziękuję za twoje pytanie. Zobacz także bibliotekę standardową. Ma moduł Singleton, tak jak FYI.
To całkiem nieźle. https://www.youtube.com/watch?v=i4uiyWA8eFk