Was genau ist die Singleton-Klasse in Ruby?


85

Ist die Singleton-Klasse in Ruby eine Klasse für sich? Ist es der Grund, warum alle Objekte zur "Klasse" gehören? Das Konzept ist verschwommen , aber ich glaube, es hat etwas damit zu tun, warum ich überhaupt eine Klassenmethode definieren kann ( class foo; def foo.bar ...).

Was ist die Singleton-Klasse in Ruby?

Antworten:


154

Zunächst eine kleine Definition: Eine Singleton-Methode ist eine Methode, die nur für ein einzelnes Objekt definiert ist. Beispiel:

irb(main):001:0> class Foo; def method1; puts 1; end; end
=> nil
irb(main):002:0> foo = Foo.new
=> #<Foo:0xb79fa724>
irb(main):003:0> def foo.method2; puts 2; end
=> nil
irb(main):004:0> foo.method1
1
=> nil
irb(main):005:0> foo.method2
2
=> nil
irb(main):006:0> other_foo = Foo.new
=> #<Foo:0xb79f0ef4>
irb(main):007:0> other_foo.method1
1
=> nil
irb(main):008:0> other_foo.method2
NoMethodError: undefined method `method2' for #<Foo:0xb79f0ef4>
        from (irb):8

Instanzmethoden sind Methoden einer Klasse (dh in der Definition der Klasse definiert). Klassenmethoden sind Singleton-Methoden für die ClassInstanz einer Klasse - sie sind in der Definition der Klasse nicht definiert. Stattdessen werden sie in der Singleton-Klasse des Objekts definiert.

irb(main):009:0> Foo.method_defined? :method1
=> true
irb(main):010:0> Foo.method_defined? :method2
=> false

Sie öffnen die Singleton-Klasse eines Objekts mit der Syntax class << obj. Hier sehen wir, dass in dieser Singleton-Klasse die Singleton-Methoden definiert sind:

irb(main):012:0> singleton_class = ( class << foo; self; end )
=> #<Class:#<Foo:0xb79fa724>>
irb(main):013:0> singleton_class.method_defined? :method1
=> true
irb(main):014:0> singleton_class.method_defined? :method2
=> true
irb(main):015:0> other_singleton_class = ( class << other_foo; self; end )
=> #<Class:#<Foo:0xb79f0ef4>>
irb(main):016:0> other_singleton_class.method_defined? :method1
=> true
irb(main):017:0> other_singleton_class.method_defined? :method2
=> false

Ein alternatives Mittel zum Hinzufügen von Singleton-Methoden zu einem Objekt besteht darin, sie bei geöffneter Singleton-Klasse des Objekts zu definieren:

irb(main):018:0> class << foo; def method3; puts 3; end; end
=> nil
irb(main):019:0> foo.method3
3
=> nil
irb(main):022:0> Foo.method_defined? :method3
=> false

Zusammenfassend:

  • Methoden müssen immer zu einer Klasse gehören (oder: Instanzmethoden einer Klasse sein)
  • Normale Methoden gehören zu der Klasse, in der sie definiert sind (dh Instanzmethoden der Klasse).
  • Klassenmethoden sind nur Singleton-Methoden von a Class
  • Singleton-Methoden eines Objekts sind keine Instanzmethoden der Klasse des Objekts. Sie sind vielmehr Instanzmethoden der Singleton-Klasse des Objekts.

17
Auf meinem Grabstein steht "RIP Ruby Singleton. Pistos hat meine geistige Gesundheit gerettet."
rmcsharry

1
@sawa Ich schätze die Absicht Ihrer Änderungen, aber ich habe das Gefühl, dass sie die Bedeutung und Kommunikation meines Beitrags ein wenig zu sehr verändern, sodass ich Ihre Änderungen zurückgesetzt habe.
Pistos

32

Ruby bietet eine Möglichkeit, Methoden zu definieren, die für ein bestimmtes Objekt spezifisch sind. Diese Methoden werden als Singleton-Methoden bezeichnet. Wenn eine Singleton-Methode für ein Objekt deklariert wird, erstellt Ruby automatisch eine Klasse, die nur die Singleton-Methoden enthält. Die neu erstellte Klasse heißt Singleton-Klasse.


    foo = Array.new
    def foo.size
      "Hello World!"
    end
    foo.size  # => "Hello World!"
    foo.class # => Array
    #Create another instance of Array Class and call size method on it
    bar = Array.new
    bar.size  # => 0
Die Singleton-Klasse ist eine objektspezifische anonyme Klasse, die automatisch erstellt und in die Vererbungshierarchie eingefügt wird.

singleton_methods kann für ein Objekt aufgerufen werden, um die Liste der Namen für alle Singleton-Methoden für ein Objekt abzurufen.

    foo.singleton_methods  # => [:size]
    bar.singleton_methods  # => []

Dieser Artikel hat mir wirklich geholfen, Singleton-Klassen in Ruby zu verstehen, und er enthält ein gutes Codebeispiel.


4
Obwohl diese Antwort über ein Jahr alt ist und der Link hilfreich ist, ist es besser, wenn Sie die wesentlichen Teile der Antwort hier auf dieser Website veröffentlichen oder Ihr Beitrag möglicherweise gelöscht wird. Lesen Sie die FAQ, in der Antworten erwähnt werden, die kaum mehr sind als ein Link '. Sie können den Link weiterhin einfügen, wenn Sie dies wünschen, jedoch nur als 'Referenz'. Die Antwort sollte für sich allein stehen, ohne den Link zu benötigen.
Taryn

stimme @bluefeet hier zu
Saurabh

Danke @bluefeet, habe die Antwort aktualisiert, um deinen Kommentar zu adressieren.
Bedasso


4

Die pragmatischste / aktionsorientierteste Art, dies zu betrachten (IMHO), ist: als Vererbungskette oder Reihenfolge der Methodensuche / -auflösung. Dieses Bild könnte helfen

http://www.klankboomklang.com/2007/11/25/modules-part-i-enter-the-include-class/

Dies ist R 1.9, im Gegensatz zu eingebauten und benutzerdefinierten Klassen: Ich verdaue diese noch.

http://d.hatena.ne.jp/sumim/20080111/p1

Ich denke auch, dass eine verwirrende Verwendung des Begriffs "Singleton-Objekt" ist, was ein anderes Konzept ist. Ein Singleton-Objekt stammt aus einer Klasse, deren Konstruktor / Instantiator-Methode überschrieben wurde, sodass Sie nur eine dieser Klassen zuweisen können.


Einer der Links ist tot. Und der andere ist Japaner!
Ulysse BN

0

Eine Singleton-Klasse ist im einfachsten Sinne eine spezielle Klasse, die Ruby-Host-Methoden für einzelne Objekte erstellt. In Ruby ist es möglich, Methoden für einzelne Objekte zu definieren, die nur für dieses Objekt eindeutig sind. Betrachten Sie zum Beispiel das Folgende unten

class User; end
user = User.new
def user.age
  "i'm a unique method"
end
user1 = User.new 
user.age #"i'm a unique method"
user1.age # NoMethodError (undefined method `age' for #<User:0x0000559c66ab7338>)

Wie Sie oben sehen können, reagiert das Objekt user1 nicht auf die Methode 'age', da es sich um eine Singleton-Methode handelt, eine Methode, die für das Benutzerobjekt eindeutig definiert ist. Zu diesem Zweck erstellt Ruby eine spezielle Klasse, die als Singleton-Klasse oder Eigenklasse bezeichnet wird, um diese einzigartige Methode zu hosten. Sie können dies überprüfen, indem Sie folgende Schritte ausführen:

user.singleton_class # #<Class:#<User:0x0000559c66b47c58>>

Sie können Ruby auch fragen, ob die Methode 'age' hier gefunden wird, indem Sie mithilfe des Methodenobjekts herausfinden, wo die Methode 'age' definiert ist. Wenn Sie dies tun, werden Sie sehen, dass die Singleton-Klasse diese Methode hat.

user_singleton_class = user.method(:age).owner # #<Class:#<User:0x0000559c66b47c58>>
user.method(:age).owner == user.singleton_class # true
user_singleton_class.instance_methods(false) # [:age]

Beachten Sie auch, dass Singleton-Methoden für eine Singleton-Klasse tatsächlich Instanzmethoden sind.

user.singleton_methods == user_singleton_class.instance_methods(false) # true
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.