web-dev-qa-db-fra.com

Quelle est exactement la classe singleton en rubis?

La classe singleton est-elle dans Ruby une classe en soi? Est-ce la raison pour laquelle tous les objets appartiennent à la "classe?" Le concept est flo, mais je crois cela a quelque chose à voir avec la raison pour laquelle je peux définir une méthode de classe (class foo; def foo.bar ...).

Qu'est-ce que la classe singleton en Ruby?

74
keyofnight

Tout d'abord, une petite définition: a méthode singleton est une méthode qui n'est définie que pour un seul objet. Exemple:

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

Les méthodes d'instance sont des méthodes d'une classe (c'est-à-dire définies dans la définition de la classe). Les méthodes de classe sont des méthodes singleton sur l'instance Class d'une classe - elles ne sont pas définies dans la définition de la classe. Au lieu de cela, ils sont définis sur la classe singleton de l'objet.

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

Vous ouvrez la classe singleton d'un objet avec la syntaxe class << obj. Ici, nous voyons que cette classe singleton est l'endroit où les méthodes singleton sont définies:

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

Ainsi, un autre moyen d'ajouter des méthodes singleton à un objet serait de les définir avec la classe singleton de l'objet ouverte:

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

En résumé:

  • les méthodes doivent toujours appartenir à une classe (ou: être des méthodes d'instance d'une classe)
  • les méthodes normales appartiennent à la classe dans laquelle elles sont définies (c'est-à-dire les méthodes d'instance de la classe)
  • les méthodes de classe ne sont que des méthodes singleton d'un Class
  • les méthodes singleton d'un objet ne sont pas des méthodes d'instance de la classe de l'objet; ce sont plutôt des méthodes d'instance de la classe singleton de l'objet.
138
Pistos

Ruby fournit un moyen de définir des méthodes spécifiques à un objet particulier et ces méthodes sont appelées méthodes singleton. Quand on déclare une méthode singleton sur un objet, Ruby crée automatiquement une classe pour contenir uniquement les méthodes singleton. La classe nouvellement créée est appelée classe Singleton.


    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

singleton_methods peut être appelé sur un objet pour obtenir la liste des noms de toutes les méthodes singleton sur un objet.

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

Cette article m'a vraiment aidé à comprendre les classes singleton dans Ruby et il a un bon exemple de code.

28
Bedasso

Comme mise à jour de la réponse @Pistos, à partir de la version 1.9.2 Ruby ajoutez une nouvelle syntaxe pour obtenir la classe singleton

 singleton_class = ( class << foo; self; end )

peut être remplacé par:

singleton_class = foo.singleton_class

https://apidock.com/Ruby/Object/singleton_class

7
Piotr Galas

La façon la plus pragmatique ou la plus orientée vers l'action (IMHO) est: comme une chaîne d'héritage, ou un ordre de recherche/résolution de méthode. Cette photo pourrait aider

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

Il s'agit de la version 1.9, qui contraste les classes intégrées et définies par l'utilisateur: je continue de digérer celle-ci.

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

En outre, je pense qu'une utilisation déroutante du terme est "objet singleton", qui est un concept différent. Un objet singleton provient d'une classe dont la méthode constructeur/instanciateur est remplacée de sorte que vous ne pouvez allouer qu'une seule de cette classe.

4
Gene T