Was ist class << self
in tun Rubin ?
Was ist class << self
in tun Rubin ?
Antworten:
Zunächst class << foo
öffnet die Syntax die foo
Singleton-Klasse (Eigenklasse). Auf diese Weise können Sie das Verhalten von Methoden spezialisieren, die für dieses bestimmte Objekt aufgerufen werden.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
Um nun die Frage zu beantworten: class << self
Öffnet die self
Singleton-Klasse, sodass Methoden für das aktuelle self
Objekt neu definiert werden können (das innerhalb eines Klassen- oder Modulkörpers die Klasse oder das Modul selbst ist ). Normalerweise wird dies verwendet, um Klassen- / Modulmethoden ("statische") zu definieren:
class String
class << self
def value_of obj
obj.to_s
end
end
end
String.value_of 42 # => "42"
Dies kann auch als Kurzform geschrieben werden:
class String
def self.value_of obj
obj.to_s
end
end
Oder noch kürzer:
def String.value_of obj
obj.to_s
end
self
Bezieht sich innerhalb einer Funktionsdefinition auf das Objekt , mit dem die Funktion aufgerufen wird. In diesem Fall wird class << self
die Singleton-Klasse für dieses Objekt geöffnet. Eine Verwendung davon ist die Implementierung der Zustandsmaschine eines armen Mannes:
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
Im obigen Beispiel StateMachineExample
hat process_hook
also jede Instanz von einen Alias für process_state_1
, aber beachten Sie, wie sie in letzterer neu definiert werden kann process_hook
( self
nur um andere StateMachineExample
Instanzen nicht zu beeinflussen ) process_state_2
. Jedes Mal, wenn ein Aufrufer die process
Methode aufruft (die die neu definierbare Methode aufruft process_hook
), ändert sich das Verhalten abhängig davon, in welchem Status sie sich befindet.
class << self
, um Klassen- / Modulmethoden zu erstellen. Ich werde wahrscheinlich auf diese Verwendung von erweitern class << self
, da dies eine viel idiomatischere Verwendung ist.
a
's zu beziehen, singleton_class
da a
die Klasse (nach dem Ändern inspect
) eine einzigartige Variante der String
Klasse ist. Wenn die Singleton- String
Klasse geändert würde, wären alle anderen String
Instanzen betroffen . Was noch seltsamer ist , dass , wenn Sie später wieder öffnen String
neu zu definieren , um inspect
dann a
abholt noch die neuen Änderungen.
class << self
dies, dass mehr als der Wert von self
gleich der Singleton-Klasse im Bereich des Blocks gesetzt wird?
Ich fand eine Super einfache Erklärung über class << self
, Eigenclass
und verschiedene Arten von Methoden.
In Ruby gibt es drei Arten von Methoden, die auf eine Klasse angewendet werden können:
Instanzmethoden und Klassenmethoden ähneln fast denen in anderen Programmiersprachen.
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
Eine andere Möglichkeit, auf eine zuzugreifen Eigenclass
(einschließlich Singleton-Methoden), ist die folgende Syntax ( class <<
):
foo = Foo.new
class << foo
def a_singleton_method
puts "I am a singleton method"
end
end
Jetzt können Sie eine Singleton-Methode definieren, für self
die Foo
in diesem Kontext die Klasse selbst ist:
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)
, um zu überprüfen.
Normalerweise sind Instanzmethoden globale Methoden. Das heißt, sie sind in allen Instanzen der Klasse verfügbar, für die sie definiert wurden. Im Gegensatz dazu ist eine Singleton-Methode für ein einzelnes Objekt implementiert.
Ruby speichert Methoden in Klassen und alle Methoden müssen einer Klasse zugeordnet sein. Das Objekt, für das eine Singleton-Methode definiert ist, ist keine Klasse (es ist eine Instanz einer Klasse). Wenn nur Klassen Methoden speichern können, wie kann ein Objekt eine Singleton-Methode speichern? Wenn eine Singleton-Methode erstellt wird, erstellt Ruby automatisch eine anonyme Klasse zum Speichern dieser Methode. Diese anonymen Klassen werden als Metaklassen bezeichnet, die auch als Singleton-Klassen oder Eigenklassen bezeichnet werden. Die Singleton-Methode ist der Metaklasse zugeordnet, die wiederum dem Objekt zugeordnet ist, für das die Singleton-Methode definiert wurde.
Wenn mehrere Singleton-Methoden in einem einzelnen Objekt definiert sind, werden sie alle in derselben Metaklasse gespeichert.
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'…
Im obigen Beispiel ändert die Klasse << z1 das aktuelle Selbst so, dass es auf die Metaklasse des z1-Objekts zeigt. Anschließend wird die say_hello-Methode innerhalb der Metaklasse definiert.
Klassen sind auch Objekte (Instanzen der integrierten Klasse namens Class). Klassenmethoden sind nichts anderes als Singleton-Methoden, die einem Klassenobjekt zugeordnet sind.
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
Alle Objekte können Metaklassen haben. Das bedeutet, dass Klassen auch Metaklassen haben können. Im obigen Beispiel ändert class << self self so, dass es auf die Metaklasse der Zabuton-Klasse verweist. Wenn eine Methode ohne expliziten Empfänger definiert wird (die Klasse / das Objekt, für die / das die Methode definiert wird), wird sie implizit innerhalb des aktuellen Bereichs definiert, dh des aktuellen Werts von self. Daher ist die Stuff-Methode in der Metaklasse der Zabuton-Klasse definiert. Das obige Beispiel ist nur eine andere Möglichkeit, eine Klassenmethode zu definieren. IMHO ist es besser, die Syntax def self.my_new_clas_method zu verwenden, um Klassenmethoden zu definieren, da dies den Code verständlicher macht. Das obige Beispiel wurde aufgenommen, damit wir verstehen, was passiert, wenn wir auf die Selbstsyntax der Klasse << stoßen.
Weitere Informationen zu Ruby-Klassen finden Sie in diesem Beitrag .
class Hi
self #=> Hi
class << self #same as 'class << Hi'
self #=> #<Class:Hi>
self == Hi.singleton_class #=> true
end
end
[es macht self == thing.singleton_class
im Kontext seines Blocks] .
hi = String.new
def hi.a
end
hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true
hi
Objekt erbt sein #methods
von seinem #singleton_class.instance_methods
und dann von seinem #class.instance_methods
.
Hier haben wir hi
‚s Singletonklasse Instanzmethode :a
. Es hätte stattdessen mit der Klasse << hi gemacht werden können.
hi
's #singleton_class
hat alle Instanzmethoden hi
' s #class
und möglicherweise noch einige mehr ( :a
hier).
[Instanzmethoden von Dingen #class
und #singleton_class
können direkt auf Dinge angewendet werden. Wenn Ruby thing.a sieht, sucht er zuerst nach: einer Methodendefinition in thing.singleton_class.instance_methods und dann in thing.class.instance_methods]
By the way - nennen sie das Objekt Singletonklasse == metaclass == Eigenklasse .
А Die Singleton-Methode ist eine Methode, die nur für ein einzelnes Objekt definiert ist.
Beispiel:
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
Singletons Methoden von SomeClass
Prüfung
Singletons Methoden von test_obj
test_2
test_3
Wenn Sie C-Erweiterungen für Ihre Ruby-Projekte schreiben, gibt es nur eine Möglichkeit, eine Modulmethode zu definieren.
rb_define_singleton_method
Ich weiß, dass dieses Selbstgeschäft einfach alle möglichen anderen Fragen aufwirft, damit Sie es besser machen können, indem Sie jedes Teil durchsuchen.
Objekte zuerst.
foo = Object.new
Kann ich eine Methode für foo erstellen?
Sicher
def foo.hello
'hello'
end
Was mache ich damit?
foo.hello
==>"hello"
Nur ein weiteres Objekt.
foo.methods
Sie erhalten alle Objektmethoden sowie Ihre neue.
def foo.self
self
end
foo.self
Nur das foo Objekt.
Versuchen Sie zu sehen, was passiert, wenn Sie aus anderen Objekten wie Klasse und Modul foo machen. Die Beispiele aus allen Antworten sind schön zu spielen, aber Sie müssen mit verschiedenen Ideen oder Konzepten arbeiten, um wirklich zu verstehen, was mit der Art und Weise, wie der Code geschrieben wird, vor sich geht. Jetzt müssen Sie sich also viele Begriffe ansehen.
Singleton, Class, Module, Self, Object und Eigenclass wurden aufgerufen, aber Ruby nennt Objektmodelle nicht so. Es ist eher wie Metaclass. Richard oder __why zeigt Ihnen die Idee hier. http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html Und wenn Sie das umhauen, versuchen Sie, Ruby Object Model bei der Suche nachzuschlagen. Zwei Videos, die ich auf YouTube kenne, sind Dave Thomas und Peter Cooper. Sie versuchen auch dieses Konzept zu erklären. Dave hat lange gebraucht, um es zu bekommen, also mach dir keine Sorgen. Ich arbeite auch noch daran. Warum sollte ich sonst hier sein? Danke für deine Frage. Schauen Sie sich auch die Standardbibliothek an. Es hat ein Singleton-Modul nur als FYI.
Das ist ziemlich gut. https://www.youtube.com/watch?v=i4uiyWA8eFk