Vererbung der Ruby-Klasse: Was ist "<<" (doppelt so viel wie)?

74
class << Awesomeness

Wofür ist das <<? Ich habe gesucht, aber die Ergebnisse sagen nur etwas über die Verkettung von Zeichenfolgen aus ...

Voldemort
quelle

Antworten:

134

Während es wahr ist, dass dies class << somethingdie Syntax für eine Singleton-Klasse ist, wie jemand anderes sagte, wird sie am häufigsten verwendet, um Klassenmethoden innerhalb einer Klassendefinition zu definieren. Diese beiden Verwendungen sind jedoch konsistent. Hier ist wie.

Mit Ruby können Sie einer bestimmten Instanz Methoden hinzufügen, indem Sie Folgendes tun:

class << someinstance
  def foo
    "Hello."
  end
end

Dies fügt einer fooInstanz eine Methode hinzu, nicht ihrer Klasse, sondern dieser einen bestimmten Instanz. (Tatsächlich wird foo zur "Singleton-Klasse" der Instanz hinzugefügt, aber das ist mehr oder weniger eine Implementierungs-Eigenart.) Nachdem der obige Code ausgeführt wurde, können Sie die Methode foo an eine Instanz senden:

someinstance.foo   => "Hello."

Sie können foo jedoch nicht an andere Instanzen derselben Klasse senden. Dafür <<ist nominell. Diese Funktion wird jedoch häufiger für syntaktische Gymnastik wie diese verwendet:

class Thing
  def do_something
  end

  class << self
    def foo
      puts "I am #{self}"
    end
  end
end

Was ist, wenn dieser Code - diese Klassendefinition - ausgeführt wird self? Es ist die Klasse Thing. Dies bedeutet, class << selfdass Sie der Klasse Thing die folgenden Methoden hinzufügen. Das heißt, foo ist eine Klassenmethode. Nachdem der obige Vorgang abgeschlossen ist, können Sie Folgendes tun:

t = Thing.new
t.do_something  => does something
t.class.foo     => "I am Thing"
t.foo           => NoMethodError: undefined method `foo'

Und wenn Sie darüber nachdenken, was <<gerade passiert, macht alles Sinn. Es ist eine Möglichkeit, an eine bestimmte Instanz anzuhängen, und im allgemeinen Fall ist die angehängte Instanz eine Klasse, sodass die Methoden innerhalb des Blocks zu Klassenmethoden werden.

Kurz gesagt, es ist eine knappe Möglichkeit, Klassenmethoden innerhalb eines Klassendefinitionsblocks zu erstellen. Ein anderer Weg wäre, dies zu tun:

class Thing
  def self.foo
    # ...
  end
end

Gleiche Sache. Ihr Beispiel ist eigentlich ein Syntaxfehler. Wenn Sie jedoch <<wissen, wie Instanzen und das Schlüsselwort class verwendet werden, wissen Sie, wie Sie ihn korrigieren können.

Rob Davis
quelle
1
Interessant! Ist eine solche Methode in der täglichen Programmierung nützlich?
Voldemort
5
@Omega: Ja, Sie würden dies zum Beispiel sehen, wenn Sie mehr als eine Methode haben, mit der Sie eine Klassenmethode erstellen möchten, und Sie nicht möchten, dass allen "self" vorangestellt wird. Sie können sie einfach alle in diesen Block legen und sich keine Sorgen machen.
Solidcell
großartige Arbeit - diese entmystifizierten anderen Antworten, auf die ich gestoßen bin.
Larry
Das letzte bisschen hat alles zum Klicken gebracht. Beachten Sie auch, dass dies class << selfin dem Sinne funktioniert, dass es sich zwar Thingum eine Klasse handelt, aber auch nur um eine Instanz ihrer Oberklasse. Klassen und Instanzen haben also nichts Besonderes. Jede Klasse in Ruby ist eine Instanz ihrer Oberklasse (außer BasicObject).
Ahnbizcad
Vielen Dank für die Erklärung, es wurde sehr gut erklärt.
Pixel 67
21

<<ist die Syntax für "Singleton-Klassendefinition" . Hier ist ein Beispiel dafür, wo / wie es "normalerweise" verwendet wird.

Darin a = "abc"; a << "xyz"ist die Syntax für "Anhängen von Daten" (an Zeichenfolge, Array usw.)

Zabba
quelle
Es wird auf diese Weise verwendet, extrahiert aus nested_form gem : simple_form_for (* (args << options), & block) << after_nested_form_callbacks
shadowbq
8
In Ruby <<heißt dasshovel operator
Pixel 67
20

Wenn Sie eine Vererbung wünschen (basierend auf Ihrem Fragentitel), möchten Sie eine einzelne <:

class Awesome < ParentAwesomeness

Der von Ihnen angegebene Code ist kein gültiger Ruby:

class Awesomeness
end

class Awesome << Awesomeness
end

SyntaxError: (irb):3: syntax error, unexpected tLSHFT, expecting '<' or ';' or '\n'
Andrew Grimm
quelle
Gut zu wissen. Dieses Faktoid ist bei der Suche schwer zu finden.
Ahnbizcad
lustig, wie wenige Leute sich den Titel angesehen haben. Die anderen Erklärungen sind großartig, haben aber irgendwie verpasst, wonach der Fragesteller gesucht hat.
ObjectNameDisplay