1005 Stimmen

Klasse << Selbst Idiom in Ruby

Was bedeutet class << self abmurksen Rubinrot ?

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

1006voto

Chris Jester-Young Punkte 212385

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.

50voto

Saman Mohamadi Punkte 3828

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:

  1. Instanzmethoden
  2. Singleton-Methoden
  3. 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

45voto

BrunoF Punkte 2833

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 .

21voto

lakesare Punkte 10044

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 .

3voto

artamonovdev Punkte 4132

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X