Was bedeutet class << self
abmurksen Rubinrot ?
Antworten
Zu viele Anzeigen?Erstens, die class << foo
Die Syntax öffnet sich foo
Singleton-Klasse (Eigenklasse). Dadurch können Sie das Verhalten von Methoden, die für dieses spezifische Objekt aufgerufen werden, spezialisieren.
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
öffnet sich self
Singleton-Klasse, damit Methoden für die aktuelle Klasse neu definiert werden können. self
Objekt (das innerhalb eines Klassen- oder Modulkörpers die Klasse oder das Modul selbst ). In der Regel wird dies verwendet, um Methoden für Klassen/Module ("statisch") 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
Innerhalb einer Funktionsdefinition, 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 Anwendung davon ist die Implementierung einer "poor man's state machine":
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
In dem obigen Beispiel wird also jede Instanz von StateMachineExample
hat process_hook
aliasiert zu process_state_1
aber beachten Sie, dass sie im letzteren Fall Folgendes neu definieren kann process_hook
(für self
nur, ohne Auswirkungen auf andere StateMachineExample
Instanzen) zu process_state_2
. Jedes Mal also, wenn ein Anrufer die process
Methode (die die umdefinierbare process_hook
), ändert sich das Verhalten, je nachdem, in welchem Zustand es sich befindet.
Ich habe 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
- Singleton-Methoden
- Methoden der Klasse
Instanzmethoden und Klassenmethoden sind ihren gleichnamigen Methoden in anderen Programmiersprachen sehr ähnlich.
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 weitere Möglichkeit des Zugriffs auf eine Eigenclass
(einschließlich der 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
können Sie nun eine Singleton-Methode definieren für self
die 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
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 nur für ein einziges Objekt implementiert.
Ruby speichert Methoden in Klassen und alle Methoden müssen mit einer Klasse verbunden sein. 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 dann 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 Metaklassen bezeichnet, auch bekannt als Singleton-Klassen oder Eigenklassen. Die Singleton-Methode ist mit der Metaklasse verbunden, die wiederum mit dem Objekt verbunden ist, für das die Singleton-Methode definiert wurde.
Wenn mehrere Singleton-Methoden innerhalb eines einzigen Objekts 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, class << z1
ändert das aktuelle self so, dass es auf die Metaklasse des z1-Objekts zeigt; dann definiert es die Methode say_hello innerhalb der Metaklasse.
Klassen sind ebenfalls Objekte (Instanzen der eingebauten Klasse Class). Klassenmethoden sind nichts anderes als Singleton-Methoden, die mit einem Klassenobjekt verbunden sind.
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
Alle Objekte können Metaklassen haben. Das bedeutet, dass auch Klassen Metaklassen haben können. Im obigen Beispiel modifiziert class << self self so, dass es auf die Metaklasse der Klasse Zabuton zeigt. Wenn eine Methode ohne expliziten Empfänger (die Klasse/das Objekt, auf dem die Methode definiert wird) definiert wird, wird sie implizit innerhalb des aktuellen Gültigkeitsbereichs definiert, d. h. dem aktuellen Wert von self. Die Methode stuff wird also innerhalb der Metaklasse der Klasse Zabuton definiert. Das obige Beispiel ist nur eine weitere 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 der Code so leichter zu verstehen ist. Das obige Beispiel wurde eingefügt, damit wir verstehen, was passiert, wenn wir auf die Syntax class << self stoßen.
Weitere Informationen finden Sie unter diesen Beitrag über Ruby-Klassen .
Was Klasse << Ding macht:
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 Zusammenhang mit seinem Block] .
Was ist thing.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 sein #methods
von seinem #singleton_class.instance_methods
und dann von seinem #class.instance_methods
.
Hier haben wir hi
's Singleton-Klasse Fallmethode :a
. Das hätte man auch mit Klasse << Hallo stattdessen.
hi
's #singleton_class
hat alle Instanzmethoden hi
's #class
hat, und möglicherweise noch einige mehr ( :a
hier).
[Instanzmethoden von thing's #class
et #singleton_class
kann direkt auf thing angewandt werden. Wenn ruby thing.a sieht, sucht es zuerst nach :a Methodendefinitionen in thing.singleton_class.instance_methods und dann in thing.class.instance_methods]
Übrigens: Sie nennen die Objekte Singleton-Klasse \== Metaklasse \== Eigenklasse .
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
Singleton's Methoden von SomeClass
Test
Singleton's Methoden von test_obj
test_2
test_3
- See previous answers
- Weitere Antworten anzeigen
42 Stimmen
Es gibt einen sehr schönen Artikel über dieses Thema von Yehuda Katz: yehudakatz.com/2009/11/15/… und Yugui: yugui.jp/articles/846
4 Stimmen
Wieder ein superschöner Artikel hier: integralist.co.uk/posts/eigenclass.html
2 Stimmen
Ich sehe dies innerhalb eines Moduls, ist das ein Unterschied? github.com/ruby/rake/blob/master/lib/rake/rake_module.rb
0 Stimmen
@FullDecent Es macht keinen Unterschied, da alles in Ruby ein Objekt ist, einschließlich Module und Klassen.
1 Stimmen
Siehe github.com/defunkt/metaid/blob/master/metaid.rb Das passt zu "Metabrille klar sehen" viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html
0 Stimmen
Die Dokumentation zu ruby-doc finden Sie unter aquí .