Primero, una pequeña definición: un método singleton es un método que se define solo para un solo objeto. Ejemplo:
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
Los métodos de instancia son métodos de una clase (es decir, definidos en la definición de la clase). Los métodos de clase son métodos singleton en la Class
instancia de una clase; no están definidos en la definición de la clase. En cambio, se definen en la clase singleton del objeto.
irb(main):009:0> Foo.method_defined? :method1
=> true
irb(main):010:0> Foo.method_defined? :method2
=> false
Abre la clase singleton de un objeto con la sintaxis class << obj
. Aquí, vemos que esta clase singleton es donde se definen los métodos singleton:
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
Entonces, un medio alternativo de agregar métodos singleton a un objeto sería definirlos con la clase singleton del objeto abierta:
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 resumen:
- los métodos siempre deben pertenecer a una clase (o: ser métodos de instancia de alguna clase)
- los métodos normales pertenecen a la clase en la que están definidos (es decir, son métodos de instancia de la clase)
- Los métodos de clase son solo métodos singleton de un
Class
- Los métodos singleton de un objeto no son métodos de instancia de la clase del objeto; más bien, son métodos de instancia de la clase singleton del objeto.
Ruby proporciona una forma de definir métodos que son específicos de un objeto en particular y dichos métodos se conocen como métodos Singleton. Cuando uno declara un método singleton en un objeto, Ruby crea automáticamente una clase para contener solo los métodos singleton. La clase recién creada se llama Clase Singleton.
La clase Singleton es una clase anónima específica de objeto que se crea e inserta automáticamente en la jerarquía de herencia.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
se puede llamar en un objeto para obtener la lista de nombres para todos los métodos singleton en un objeto.foo.singleton_methods # => [:size] bar.singleton_methods # => []
Este artículo realmente me ayudó a comprender las clases Singleton en Ruby y tiene un buen ejemplo de código.
fuente
Como acaba de actualizar a la respuesta de @Pistos, desde la versión 1.9.2 ruby agregue una nueva sintaxis para obtener la clase singleton
singleton_class = ( class << foo; self; end )
se puede reemplazar con:
https://apidock.com/ruby/Object/singleton_class
fuente
La forma más pragmática / basada en la acción de pensarlo (en mi humilde opinión) es: como una cadena de herencia, o un orden de búsqueda / resolución de métodos. Esta imagen puede ayudar
http://www.klankboomklang.com/2007/11/25/modules-part-i-enter-the-include-class/
Esto es r 1.9, contrastando las clases integradas y definidas por el usuario: todavía estoy digiriendo esta.
http://d.hatena.ne.jp/sumim/20080111/p1
Además, creo que un uso confuso del término es "Objeto Singleton", que es un concepto diferente. Un objeto singleton proviene de una clase que tiene su método constructor / instanciador anulado para que pueda asignar solo uno de esa clase.
fuente
Una clase singleton en los términos más simples es una clase especial que ruby se adapta a métodos de host definidos en objetos individuales. En ruby, es posible definir métodos en objetos individuales que son exclusivos de ese objeto solo. Por ejemplo, considere lo siguiente a continuación
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>)
Como puede ver arriba, el objeto user1 no responde al método 'age' porque es un método singleton, un método definido de forma única en el objeto del usuario. Para que esto suceda, ruby crea una clase especial, llamada clase singleton o clase propia, para alojar este método único. Puede verificar esto haciendo lo siguiente:
user.singleton_class # #<Class:#<User:0x0000559c66b47c58>>
También puede preguntarle a ruby si el método 'edad' se encuentra aquí utilizando el objeto de método para averiguar dónde está definido el método 'edad'. Cuando hagas esto, verás que la clase singleton tiene ese método.
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]
También tenga en cuenta que, en lo que respecta a una clase singleton, los métodos singleton son en realidad sus métodos de instancia.
user.singleton_methods == user_singleton_class.instance_methods(false) # true
fuente