clase << self idioma en Ruby

¿Qué hace el class << self en Ruby?

Primero, la syntax class < < foo abre la clase singleton de foo (eigenclass). Esto le permite especializar el comportamiento de los métodos llamados en ese objeto específico.

 a = 'foo' class < < a def inspect '"bar"' end end a.inspect # => "bar" a = 'foo' # new object, new singleton class a.inspect # => "foo" 

Ahora, para responder a la pregunta: class < < self opens 'single class' s, para que los métodos puedan redefinirse para el objeto actual (que dentro de una clase o cuerpo de módulo es la clase o módulo en ). Por lo general, esto se usa para definir métodos de clase / módulo ("estáticos"):

 class String class < < self def value_of obj obj.to_s end end end String.value_of 42 # => "42" 

Esto también se puede escribir como una taquigrafía:

 class String def self.value_of obj obj.to_s end end 

O incluso más corto:

 def String.value_of obj obj.to_s end 

Cuando dentro de una definición de función, self refiere al objeto con el que se está llamando a la función. En este caso, class < < self abre la clase singleton para ese objeto; un uso de eso es implementar la máquina de estado de un hombre pobre:

 class StateMachineExample def process obj process_hook obj end private def process_state_1 obj # ... class < < self alias process_hook process_state_2 end end def process_state_2 obj # ... class << self alias process_hook process_state_1 end end # Set up initial state alias process_hook process_state_1 end 

Por lo tanto, en el ejemplo anterior, cada instancia de StateMachineExample tiene un alias de process_state_1 para process_state_1 , pero tenga en cuenta cómo en este último, puede redefinir process_hook (solo para self , sin afectar a otras instancias de StateMachineExample ) para process_state_2 . Por lo tanto, cada vez que una persona llama al método de process (que llama al redefinible process_hook ), el comportamiento cambia dependiendo de en qué estado se encuentre.

Encontré una explicación súper simple sobre class < < self , Eigenclass y diferentes tipos de methods en este blog .

En Ruby, hay tres tipos de métodos que se pueden aplicar a una clase:

  1. Métodos de instancia
  2. Métodos Singleton
  3. Métodos de clase

Los métodos de instancia y los métodos de clase son casi similares a sus homónimos en otros lenguajes de progtwigción.

 class Foo def an_instance_method puts "I am an instance method" end def self.a_class_method puts "I am a class method" end end foo = Foo.new def foo.a_singleton_method puts "I am a singletone method" end 

Otra forma de acceder a una Eigenclass (que incluye métodos singleton) es con la siguiente syntax ( class < < ):

 foo = Foo.new class < < foo def a_singleton_method puts "I am a singleton method" end end 

ahora puedes definir un método singleton para self que es la clase Foo en este contexto:

 class Foo class < < self def a_singleton_and_class_method puts "I am a singleton method for self and a class method for Foo" end end end 

¿Qué clase < < cosa hace:

 class Hi self #=> Hi class < < self #same as 'class << Hi' self #=> # self == Hi.singleton_class #=> true end end 

[hace self == thing.singleton_class en el contexto de su bloque] .


¿Qué es thing.singleton_class?

 hi = String.new def hi.a end hi.class.instance_methods.include? :a #=> false hi.singleton_class.instance_methods.include? :a #=> true 

hi objeto hereda sus #singleton_class.instance_methods #methods de sus #singleton_class.instance_methods y luego de su #class.instance_methods .
Aquí le dimos el método de instancia de clase singleton de hi :a . Podría haberse hecho con la clase < < hi en su lugar.
La #singleton_class hi tiene todos los métodos de instancia que tiene la #singleton_class hi , y posiblemente algunos más ( :a aquí).

[los métodos de instancia de thing’s #class y #singleton_class se pueden aplicar directamente a thing. cuando ruby ​​ve thing.a, primero busca: una definición de método en thing.singleton_class.instance_methods y luego en thing.class.instance_methods]


Por cierto, ellos llaman a la clase singleton del objeto == metaclass == eigenclass .

Por lo general, los métodos de instancia son métodos globales. Eso significa que están disponibles en todas las instancias de la clase en la que se definieron. Por el contrario, un método singleton se implementa en un solo objeto.

Ruby almacena métodos en clases y todos los métodos deben estar asociados con una clase. El objeto sobre el que se define un método singleton no es una clase (es una instancia de una clase). Si solo las clases pueden almacenar métodos, ¿cómo puede un objeto almacenar un método singleton? Cuando se crea un método singleton, Ruby crea automáticamente una clase anónima para almacenar ese método. Estas clases anónimas se llaman metaclases, también conocidas como clases únicas o clases propias. El método singleton está asociado con la metaclase que, a su vez, está asociada con el objeto sobre el que se definió el método singleton.

Si se definen múltiples métodos únicos dentro de un solo objeto, todos se almacenan en la misma metaclase.

 class Zen end z1 = Zen.new z2 = Zen.new class < < z1 def say_hello puts "Hello!" end end z1.say_hello # Output: Hello! z2.say_hello # Output: NoMethodError: undefined method `say_hello'… 

En el ejemplo anterior, la clase < < z1 cambia el yo actual para apuntar a la metaclase del objeto z1; luego, define el método say_hello dentro de la metaclase.

Las clases también son objetos (instancias de la clase incorporada llamada Clase). Los métodos de clase no son más que métodos únicos asociados con un objeto de clase.

 class Zabuton class < < self def stuff puts "Stuffing zabuton…" end end end 

Todos los objetos pueden tener metaclases. Eso significa que las clases también pueden tener metaclases. En el ejemplo anterior, la clase < < se auto modifica a sí misma, por lo que apunta a la metaclase de la clase Zabuton. Cuando se define un método sin un receptor explícito (la clase / objeto sobre el que se definirá el método), se define implícitamente dentro del alcance actual, es decir, el valor actual de uno mismo. Por lo tanto, el método de cosas se define dentro de la metaclase de la clase Zabuton. El ejemplo anterior es solo otra forma de definir un método de clase. En mi humilde opinión, es mejor utilizar la sintaxis def self.my_new_clas_method para definir los métodos de clase, ya que hace que el código sea más fácil de entender. El ejemplo anterior fue incluido, así que entendemos lo que sucede cuando encontramos la sintaxis de clase << self.

Información adicional se puede encontrar en este post sobre Ruby Classes .

Un método singleton es un método que está definido solo para un solo objeto.

Ejemplo:

 class SomeClass class < < self def test end end end test_obj = SomeClass.new def test_obj.test_2 end class << test_obj def test_3 end end puts "Singleton's methods of SomeClass" puts SomeClass.singleton_methods puts '------------------------------------------' puts "Singleton's methods of test_obj" puts test_obj.singleton_methods 

Los métodos de SingleClass de Singleton

prueba


Los métodos Singleton de test_obj

test_2

prueba_3

De hecho, si escribe extensiones C para sus proyectos de Ruby, en realidad solo hay una forma de definir un método de Módulo.

 rb_define_singleton_method 

Sé que este negocio propio simplemente abre todo tipo de otras preguntas para que puedas mejorar buscando cada parte.

Objetos primero.

 foo = Object.new 

¿Puedo hacer un método para foo?

Por supuesto

 def foo.hello 'hello' end 

¿Que hago con esto?

 foo.hello ==>"hello" 

Solo otro objeto.

 foo.methods 

Obtienes todos los métodos Object más tu nuevo.

 def foo.self self end foo.self 

Solo el objeto Foo.

Intenta ver qué sucede si haces foo desde otros objetos como clase y módulo. Los ejemplos de todas las respuestas son agradables para jugar, pero debe trabajar con diferentes ideas o conceptos para comprender realmente lo que está sucediendo con la forma en que se escribe el código. Entonces ahora tienes muchos términos para ver.

Singleton, Class, Module, self, Object y Eigenclass se mencionaron pero Ruby no nombra los Object Models de esa manera. Es más como Metaclass. Richard o __why te muestra la idea aquí. http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html Y si te sorprende, intenta buscar Ruby Object Model en la búsqueda. Dos videos que conozco en YouTube son Dave Thomas y Peter Cooper. Intentan explicar ese concepto también. Dave tardó mucho tiempo en conseguirlo, así que no te preocupes. Todavía estoy trabajando en eso también. ¿Por qué más estaría aquí? Gracias por tu pregunta También eche un vistazo a la biblioteca estándar. Tiene un Módulo Singleton solo como un FYI.

Esto es bastante bueno https://www.youtube.com/watch?v=i4uiyWA8eFk