clase << modismo propio en Ruby

Resuelto randombits asked hace 14 años • 6 respuestas

¿Qué hace class << selfen Ruby ?

randombits avatar Mar 24 '10 10:03 randombits
Aceptado

Primero, la class << foosintaxis abre foola clase singleton (clase propia). 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 << selfabre selfla clase singleton de , de modo que los métodos se pueden redefinir para el selfobjeto actual (que dentro de una clase o cuerpo de módulo es la clase o módulo en sí ). Normalmente, esto se utiliza 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 abreviatura:

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 está dentro de la definición de una función, selfse refiere al objeto con el que se llama a la función. En este caso, class << selfabre la clase singleton para ese objeto; un uso de eso es implementar la máquina de estados 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 StateMachineExampletiene process_hookun alias process_state_1, pero observe cómo en este último, puede redefinirse process_hook( selfsolo para no afectar otras StateMachineExampleinstancias) a process_state_2. Entonces, cada vez que una persona que llama llama al processmétodo (que llama al redefinible process_hook), el comportamiento cambia dependiendo del estado en el que se encuentre.

C. K. Young avatar Mar 24 '2010 03:03 C. K. Young

Encontré una explicación súper simple sobre class << selfy Eigenclassdiferentes tipos de métodos.

En Ruby, existen 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 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 puedes definir un método singleton para selfel cual es la clase Foomisma 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
Saman Mohamadi avatar Jan 29 '2016 11:01 Saman Mohamadi

Normalmente, 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 fueron definidos. Por el contrario, un método singleton se implementa en un único objeto.

Ruby almacena 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 sólo 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 denominan metaclases, también conocidas como clases singleton o clases propias. El método singleton está asociado con la metaclase que, a su vez, está asociada con el objeto en el que se definió el método singleton.

Si se definen varios 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, class << z1cambia el self actual para que apunte 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 integrada 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, class << self modifica self para que apunte a la metaclase de la clase Zabuton. Cuando un método se define 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 cosas se define dentro de la metaclase de la clase Zabuton. El ejemplo anterior es sólo 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 qué sucede cuando nos encontramos con la clase << self sintaxis.

Puede encontrar información adicional en esta publicación sobre Ruby Classes .

BrunoF avatar Jun 26 '2016 18:06 BrunoF

¿Qué clase << cosa hace:

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

[lo 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

hiEl objeto hereda su #methodsde su #singleton_class.instance_methodsy luego de su #class.instance_methods.
Aquí proporcionamos hiel método de instancia de clase singleton:a . Se podría haber hecho con la clase << hola en su lugar.
hiTiene #singleton_classtodos los métodos de instancia hique #classtiene y posiblemente algunos más ( :aaquí).

[Métodos de instancia de una cosa #class y #singleton_class se pueden aplicar directamente a la cosa. 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, llaman al objeto singleton class == metaclass == eigenclass .

Evgenia Karunus avatar Nov 12 '2015 14:11 Evgenia Karunus