Ruby Language                
            Classe Singleton
        
        
            
    Recherche…
Syntaxe
- singleton_class = class << objet; fin de soi
Remarques
 Les classes singleton n'ont qu'une seule instance: leur objet correspondant. Cela peut être vérifié en interrogeant le ObjectSpace de Ruby: 
instances = ObjectSpace.each_object object.singleton_class
instances.count            # => 1
instances.include? object  # => true
 En utilisant < , ils peuvent également être vérifiés pour être des sous-classes de la classe réelle de l'objet: 
object.singleton_class < object.class  # => true
Les références:
introduction
Ruby a trois types d'objets:
- Classes et modules qui sont des instances de classe Class ou class Module.
- Instances de classes.
- Classes Singleton.
Chaque objet a une classe qui contient ses méthodes:
class Example
end
object = Example.new
object.class  # => Example
Example.class # => Class
Class.class   # => Class
Les objets eux-mêmes ne peuvent pas contenir de méthodes, seule leur classe le peut. Mais avec les classes singleton, il est possible d'ajouter des méthodes à n'importe quel objet, y compris d'autres classes singleton.
def object.foo
  :foo
end
object.foo #=> :foo
 foo est défini sur la classe singleton de l' object . Autres Example exemples ne peuvent pas répondre à foo . 
Ruby crée des classes singleton à la demande. Leur accès ou leur ajout de méthodes force Ruby à les créer.
Accéder à la classe Singleton
Il y a deux façons d'obtenir la classe singleton d'un objet
-  Méthode singleton_class.
-  Réouverture de la classe singleton d'un objet et retour self.
object.singleton_class
singleton_class = class << object
  self
end
Accès aux variables d'instance / classe dans les classes Singleton
Les classes Singleton partagent leurs variables d'instance / classe avec leur objet.
class Example
  @@foo = :example
end
def Example.foo
  class_variable_get :@@foo
end
Example.foo #=> :example
class Example
  def initialize
    @foo = 1
  end
  def foo
    @foo
  end
end
e = Example.new
e.instance_eval <<-BLOCK
  def self.increase_foo
    @foo += 1
  end
BLOCK
e.increase_foo
e.foo #=> 2
 Les blocs se rapprochent de la cible de leurs variables instance / classe. L'accès aux variables d'instance ou de classe à l'aide d'un bloc dans class_eval ou instance_eval n'est pas possible. Passer une chaîne à class_eval ou utiliser class_variable_get fonctionne autour du problème. 
class Foo
  @@foo = :foo
end
class Example
  @@foo = :example 
  Foo.define_singleton_method :foo do
    @@foo
  end
end
Foo.foo #=> :example
Héritage de la classe Singleton
Le sous-classement comprend également les sous-classes de la classe Singleton
class Example
end
Example.singleton_class #=> #<Class:Example>
def Example.foo
  :example
end
class SubExample < Example
end
SubExample.foo #=> :example
SubExample.singleton_class.superclass #=> #<Class:Example>
L'extension ou l'inclusion d'un module n'élargit pas la classe Singleton
module ExampleModule
end
def ExampleModule.foo
  :foo
end
class Example
  extend ExampleModule
  include ExampleModule
end
Example.foo #=> NoMethodError: undefined method
Propagation des messages avec la classe Singleton
Les instances ne contiennent jamais une méthode qu'elles ne transportent que des données. Cependant, nous pouvons définir une classe singleton pour tout objet incluant une instance d'une classe.
Lorsqu'un message est transmis à un objet (la méthode est appelée), Ruby vérifie tout d'abord si une classe singleton est définie pour cet objet et si elle peut répondre à ce message, sinon Ruby vérifie la chaîne des ancêtres de la classe
class Example
  def foo
    :example
  end
end
Example.new.foo #=> :example
module PrependedModule
  def foo
    :prepend
  end
end
class Example
  prepend PrependedModule
end
Example.ancestors #=> [Prepended, Example, Object, Kernel, BasicObject]
e = Example.new
e.foo #=> :prepended
def e.foo
  :singleton
end
e.foo #=> :singleton
Réouverture (correction de singe) Classes Singleton
Il existe trois façons de rouvrir une classe Singleton
-  Utiliser class_evalsur une classe singleton.
-  Utilisation de la class <<block
-  Utilisation de defpour définir une méthode directement sur la classe singleton de l'objet
class Example
end
Example.singleton_class.class_eval do
  def foo
    :foo
  end
end
Example.foo #=> :foo
class Example
end
class << Example
  def bar
    :bar
  end
end
Example.bar #=> :bar
class Example
end
def Example.baz
  :baz
end
Example.baz #=> :baz
Chaque objet a une classe singleton à laquelle vous pouvez accéder
class Example
end
ex1 = Example.new
def ex1.foobar
  :foobar
end
ex1.foobar #=> :foobar
ex2 = Example.new
ex2.foobar #=> NoMethodError
Classes Singleton
Tous les objets sont des instances d'une classe. Cependant, ce n'est pas toute la vérité. Dans Ruby, chaque objet a également une classe singleton quelque peu cachée.
C'est ce qui permet de définir des méthodes sur des objets individuels. La classe singleton se situe entre l'objet lui-même et sa classe réelle, de sorte que toutes les méthodes définies sur cet objet sont disponibles pour cet objet, et cet objet uniquement.
object = Object.new
def object.exclusive_method
  'Only this object will respond to this method'
end
object.exclusive_method
# => "Only this object will respond to this method"
Object.new.exclusive_method rescue $!
# => #<NoMethodError: undefined method `exclusive_method' for #<Object:0xa17b77c>>
 L'exemple ci-dessus aurait pu être écrit en utilisant define_singleton_method : 
object.define_singleton_method :exclusive_method do
  "The method is actually defined in the object's singleton class"
end
 Ce qui revient à définir la méthode sur singleton_class object : 
# send is used because define_method is private
object.singleton_class.send :define_method, :exclusive_method do
  "Now we're defining an instance method directly on the singleton class"
end
 Avant l'existence de singleton_class dans le cadre de l'API principale de Ruby, les classes singleton étaient connues sous le nom de métaclasses et pouvaient être accédées via l'idiome suivant: 
class << object
  self  # refers to object's singleton_class
end