Klasse << Selbstidiom in Ruby
-
22-09-2019 - |
Frage
Was macht class << self
in Ruby tun?
Lösung
Zuerst die class << foo
Syntax öffnet sich foo
's Singleton -Klasse (Eigenclass). Auf diese Weise können Sie das Verhalten von Methoden spezialisiert, die dieses spezifische Objekt aufrufen.
a = 'foo'
class << a
def inspect
'"bar"'
end
end
a.inspect # => "bar"
a = 'foo' # new object, new singleton class
a.inspect # => "foo"
Nun, um die Frage zu beantworten: class << self
eröffnet self
Die Singleton -Klasse, damit Methoden für den Strom neu definiert werden können self
Objekt (das in einer Klasse oder einem Modulkörper ist die Klasse oder das Modul selbst). Normalerweise wird dies verwendet, um Klassen/Modul ("statische") Methoden 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 Abkürzung 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
Wenn Sie in einer Funktionsdefinition in einer Funktionsdefinition sind, self
Bezieht sich auf das Objekt, mit dem die Funktion aufgerufen wird. In diesem Fall, class << self
öffnet die Singleton -Klasse für dieses Objekt; Eine Verwendung davon besteht darin, die Staatsmaschine eines armen Mannes zu implementieren:
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
Also im obigen Beispiel jede Instanz von StateMachineExample
hat process_hook
Alias process_state_1
, aber beachten Sie, wie es in letzterem neu definieren kann process_hook
(zum self
nur, nicht andere beeinflussen StateMachineExample
Instanzen) zu process_state_2
. Jedes Mal, wenn ein Anrufer das anruft process
Methode (die die neu definierbare Aufrufe nennt process_hook
), Das Verhalten ändert sich je nach Zustand, in dem es sich befindet.
Andere Tipps
Ich fand eine super einfache Erklärung zu class << self
, Eigenclass
und unterschiedliche Art von methods
in diesem Blog.
In Ruby gibt es drei Arten von Methoden, die auf eine Klasse angewendet werden können:
- Instanzmethoden
- Singleton -Methoden
- Klassenmethoden
Instanzmethoden und Klassenmethoden ähneln in anderen Programmiersprachen fast ihrem Homonymous.
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 einen zuzugreifen Eigenclass
(einschließlich Singleton -Methoden) ist mit der folgenden 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 für definieren self
Welches ist die Klasse Foo
selbst in diesem Zusammenhang:
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
In der Regel sind Instanzmethoden globale Methoden. Das bedeutet, dass sie in allen Fällen der Klasse verfügbar sind, in denen sie definiert wurden. Im Gegensatz dazu wird eine Singleton -Methode auf einem einzelnen Objekt implementiert.
Ruby speichert Methoden in Klassen und alle Methoden müssen mit einer Klasse in Verbindung gebracht werden. Das Objekt, auf dem 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, um diese Methode zu speichern. Diese anonymen Klassen werden als Metaklasse bezeichnet, auch als Singleton -Klassen oder Eigenklassen bezeichnet. Die Singleton -Methode ist mit der Metaklas verbunden, die wiederum dem Objekt zugeordnet ist, auf dem die Singleton -Methode definiert wurde.
Wenn mehrere Singleton -Methoden in einem einzelnen Objekt definiert sind, werden sie alle in derselben Metaklas 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 Klasse << Z1 das aktuelle Selbst, um auf die Metaklasse des Z1 -Objekts zu verweisen. Dann definiert es die Say_hello -Methode innerhalb der Metaklasse.
Klassen sind auch Objekte (Instanzen der integrierten Klasse namens Klasse). 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 Metaklasse haben. Das bedeutet, dass Klassen auch Metaklasse haben können. Im obigen Beispiel verändert die Klasse << Selbst das Selbst, so dass es auf die Metaklasse der Zabuton -Klasse weist. Wenn eine Methode ohne expliziten Empfänger definiert wird (die Klasse/das Objekt, auf der die Methode definiert wird), ist sie implizit im aktuellen Bereich definiert, dh im aktuellen Wert des Selbst. Daher wird die Stuff -Methode in der Metaklasse der Zabuton -Klasse definiert. Das obige Beispiel ist nur eine weitere Möglichkeit, eine Klassenmethode zu definieren. IMHO, es ist besser, das Def self zu verwenden. Das obige Beispiel wurde enthalten, damit wir verstehen, was passiert, wenn wir auf die Klasse << Selbstsyntax stoßen.
Zusätzliche Informationen finden Sie unter Dieser Beitrag über Ruby -Klassen.
Welche Klasse << Ding tut:
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.
Was ist Ding.singleton_class?
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 seine #methods
von seinem #singleton_class.instance_methods
und dann von seinem #class.instance_methods
.
Hier gaben wir hi
's Singleton -Klasse Instanzmethode :a
. Es hätte mit erledigt werden können mit Klasse << hi stattdessen.
hi
's #singleton_class
hat alle Instanzmethoden hi
's #class
hat und möglicherweise einige mehr (:a
hier).
Instanzmethoden von Dingen #class
und #singleton_class
kann direkt auf Dinge angewendet werden. Wenn Ruby etwas sieht.a, sucht es zuerst nach: eine Methode Definition in Thing.singleton_class.instance_methods und dann in Thing.class.instance_methods
Übrigens - sie nennen Objekte Singleton -Klasse == Metaklas == Eigenclass.
А 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 der Someklasse
Prüfung
Singletons Methoden von test_obj
test_2
test_3
Wenn Sie C -Erweiterungen für Ihre Ruby -Projekte schreiben, gibt es wirklich nur eine Möglichkeit, eine Modulmethode zu definieren.
rb_define_singleton_method
Ich weiß, dass dieses Selbstgeschäft nur alle möglichen anderen Fragen eröffnet, sodass Sie es besser machen können, indem Sie jeden 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 Foo aus anderen Objekten wie Klasse und Modul machen. Die Beispiele aller 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 geschrieben wird, wie der Code geschrieben wird. Jetzt haben Sie also viele Begriffe zu sehen.
Singleton, Klasse, Modul, Selbst, Objekt und Eigenklass wurden angesprochen, aber Ruby nennt Objektmodelle nicht so. Es ist eher wie Metaclass. Richard oder __why zeigt Ihnen hier die Idee.http://viewsourcecode.org/why/hacking/seeingmetaclassesclearly.htmlUnd wenn Sie sich wegblasen, versuchen Sie, das Ruby -Objektmodell auf der Suche nachzuschlagen. Zwei Videos, die ich auf YouTube kenne, sind Dave Thomas und Peter Cooper. Sie versuchen auch, dieses Konzept zu erklären. Es dauerte lange, bis Dave es bekam, also mach dir keine Sorgen. Ich arbeite auch immer noch daran. Warum wäre ich sonst hier? Vielen Dank für Ihre Frage. Schauen Sie sich auch die Standardbibliothek an. Es hat ein Singleton -Modul wie eine FYI.
Das ist ziemlich gut.https://www.youtube.com/watch?v=i4uiywa8efk