2010-07-07 13 views
12

¿Puedo crear clases de Ruby dentro de los cuerpos de las funciones? Parece que recibo un error que me dice que no está permitido, pero creo que debería ser así porque las clases son demasiados objetos aquí.¿Por qué no pueden haber clases dentro de los métodos en Ruby?

 
class A 
    def method 
     class B 
     end 
    end 
end

Esto falla con la definición de la clase de error dentro del cuerpo del método. Si no podemos, ¿por qué no podemos crear clases dentro de los métodos?

+2

¿por qué querrías hacer esto? –

+0

@Mark - Hago esto todo el tiempo con objetos anónimos en C#. Por supuesto, no tienen métodos per se, pero sigue siendo una razón válida para querer crear una clase sobre la marcha. Un objeto de contenedor efímero para contener temporalmente algunos datos que puedo usar de manera fuertemente tipada (al menos haciendo referencia a propiedades por nombre) es realmente útil. – tvanfosson

+0

@ Mark- exactamente como dijo tvanfosson! –

Respuesta

8
class A 
    def method 
    self.class.const_set :B, Class.new { 
     def foo 
     'bar' 
     end 
    } 
    end 
end 

A.new.method 
A::B.new.foo # => 'bar' 

Sin embargo, ¿por qué quiere asignar una constante dentro de un método? Eso no tiene sentido: las constantes son constante, solo puede asignarlas una vez, lo que significa que solo puede ejecutar su método una vez. Entonces, ¿por qué escribes un método, si es que alguna vez se ejecutará una sola vez?

+4

Puedo pensar en varios patrones que podrían concebiblemente definir clases en un método, más notablemente cosas como puentes, adaptadores y fábricas. Sería útil si necesita obtener algún recurso estático (como una conexión LDAP), pero no desea dictar la implementación (por ejemplo, net/ldap vs ruby-net-ldap). Aún así, está lejos de ser una necesidad cotidiana. –

+0

Quiero que la clase sea una instancia de acción local. De modo que las instancias de clase están condenadas a ser basura recolectada una vez que se termina la acción.A saber, hago una solicitud de jabón, lo analizo como instancias de alguna clase (para que respondan a algunas llamadas). Y pase '@ things' a la vista. Una vez que se muestra la vista, no quiero recordar '@ things' en absoluto. – Adobe

10

puede crear clases, pero no puede asignar constantes desde dentro de un método.

este ejemplo funciona:

class A 
    def a 
    b = Class.new 
    def b.xxx 
     "XXX" 
    end 
    b 
    end 
end 

a = A.new.a 
p a   # #<Class:0x7fa74fe6cc58> 
p a.xxx  # "XXX" 
+0

Esta es una mejor respuesta. OP quería saber ** por qué **. Usted ha explicado por qué. –

+0

Su pregunta era sobre la definición de una clase dentro de un método, sin instanciar una. Esta respuesta no aborda la pregunta. – Gewthen

8

puede crear clases desde el interior de los métodos y asignarlos a una constante, como en el siguiente

class A 
    def create_class class_name 
    new_class = Class.new 
    new_class.send :define_method, :speak do 
     "Hi, There" 
    end 
    Object.const_set class_name, new_class 
    end 
end 

A.new.create_class "Harry" 
h = Harry.new 
puts h.speak # responds => "Hi, There" 

porque un nombre de clase como en la cadena es sólo una constante en ruby ​​a diferencia de muchos otros idiomas.

4

La cuestión es sobre la creación de clases, pero en el comentario se habla de crear objetos anónimos. No es lo mismo.

Si necesita un objeto anónimo, siempre puede hacer Object.new. Si necesita un contenedor simple similar a una estructura, debe echar un vistazo a la clase Struct. Con él, usted puede hacer algo como:

def foo 
    anon_obj = Struct.new(:prop1, :prop2).new 
    anon_obj.prop1 = 123 
    anon_obj.prop2 = 'bar' 

    return anon_obj 
end 

Por cierto, Ruby es un lenguaje fuertemente tipado. Pero también es un tipo dinámico, y no se puede esperar que se comporte como estático.

Cuestiones relacionadas