clase<< auto modismo en Ruby
metaclass eigenclass (6)
Que clase << cosa hace:
class Hi
self #=> Hi
class << self #same as ''class << Hi''
self #=> #<Class:Hi>
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
desde su #singleton_class.instance_methods
y luego desde su #class.instance_methods
.
Aquí dimos el método de instancia de clase singleton de hi
:a
. Se podría haber hecho con clase << hola en su lugar.
hi
''s #singleton_class
tiene todos los métodos de instancia hi
'' s #class
tiene, y posiblemente algunos más ( :a
aquí).
[los métodos de instancia de thing #class
y #singleton_class
pueden aplicarse 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 .
¿Qué hace la class << self
mismo en Ruby?
De hecho, si escribe alguna extensión en 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 solo abre todo tipo de otras preguntas para que pueda hacerlo mejor 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 de objetos más tu nuevo.
def foo.self
self
end
foo.self
Sólo el objeto foo.
Intenta ver qué sucede si haces foo con otros Objetos como Clase y Módulo. Es bueno jugar con los ejemplos de todas las respuestas, pero tienes que trabajar con diferentes ideas o conceptos para entender realmente lo que está sucediendo con la forma en que se escribe el código. Así que ahora tienes muchos términos que ver.
Singleton, Class, Module, self, Object y Eigenclass se mencionaron, pero Ruby no nombra los Modelos de Objetos de esa manera. Es más como metaclase. Richard o __why te muestra la idea aquí. viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html Y, si se queda atrás, intente buscar el Modelo de objetos Ruby en la búsqueda. Dos videos que conozco en YouTube son Dave Thomas y Peter Cooper. Intentan explicar ese concepto también. A Dave le llevó mucho tiempo conseguirlo, así que no te preocupes. Todavía estoy trabajando en eso también. ¿Por qué otra cosa 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
Encontré una explicación super simple sobre la class << self
, Eigenclass
y diferentes tipos de methods
en este integralist.co.uk/posts/eigenclass.html .
En Ruby, hay tres tipos de métodos que pueden aplicarse a una clase:
- Metodos de instancia
- Métodos singleton
- 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 programació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 un Eigenclass
(que incluye métodos singleton) es con la siguiente sintaxis ( class <<
):
foo = Foo.new
class << foo
def a_singleton_method
puts "I am a singleton method"
end
end
ahora puede 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
Primero, la class << foo
syntax 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
abre self
clase singleton de self
, de modo que los métodos pueden redefinirse para el objeto self
actual (que dentro de una clase o módulo es la clase o el módulo en sí ). Generalmente, esto se usa para definir los métodos de clase / módulo ("estático"):
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 se encuentra dentro de una definición de función, self
refiere al objeto con el que se llama a la función. En este caso, la 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
Entonces, en el ejemplo anterior, cada instancia de StateMachineExample
tiene process_hook
alias para process_state_1
, pero observe cómo en este último, puede redefinir process_hook
(solo para el StateMachineExample
, sin afectar a otras instancias de StateMachineExample
) a process_state_2
. Por lo tanto, cada vez que una persona que llama llama al método de process
(que llama a process_hook
redefinible), el comportamiento cambia según el estado en que se encuentre.
Un método singleton es un método que se define 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 Singleton de SomeClass
prueba
Métodos singleton de test_obj
prueba_2
prueba_3
Usualmente, 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. En contraste, un método singleton se implementa en un solo objeto.
Ruby almacena los métodos en clases y todos los métodos deben estar asociados con una clase. El objeto en 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 singleton o eigenclasses. El método singleton está asociado con la metaclase que, a su vez, está asociado con el objeto en el que se definió el método singleton.
Si se definen múltiples métodos singleton 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 self actual para apuntar a la metaclase del objeto z1; entonces, 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 singleton 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 << self se modifica a sí mismo para que apunte a la metaclase de la clase Zabuton. Cuando se define un método sin un receptor explícito (la clase / objeto en el que se definirá el método), se define implícitamente dentro del alcance actual, es decir, el valor actual de self. Por lo tanto, el método de relleno 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 usar la sintaxis def self.my_new_clas_method para definir métodos de clase, ya que hace que el código sea más fácil de entender. El ejemplo anterior se incluyó para que entendamos lo que está sucediendo cuando nos encontramos con la sintaxis propia de la clase <<
Se puede encontrar información adicional en este post sobre Ruby Classes .