Como se mencionó anteriormente, la forma sensata de hacerlo es con Struct
o definiendo un método Test#initialize
. Esto es exactamente para lo que son las estructuras y los constructores. Usando un hash de opciones correspondiente a atributos es el equivalente más cercano de su ejemplo de C#, y es una convención Rubí-aspecto normal:
t = Test.new({:name => "something"})
t = Test.new(name: "something") # json-style or kwargs
Pero en su ejemplo que está haciendo algo que se parece más a la asignación de variables utilizando =
así que vamos a intente usar un bloque en lugar de un hash. (También está utilizando Name
que sería una constante en Ruby, vamos a cambiar eso.)
t = Test.new { @name = "something" }
fresca, Ahora vamos a hacer que realmente funcionan:
class BlockInit
def self.new(&block)
super.tap { |obj| obj.instance_eval &block }
end
end
class Test < BlockInit
attr_accessor :name
end
t = Test.new { @name = "something" }
# => #<Test:0x007f90d38bacc0 @name="something">
t.name
# => "something"
Hemos creado una clase con un constructor que acepta un argumento de bloque, que se ejecuta dentro del objeto recién instanciado.
Debido a que usted ha dicho que quería evitar el uso de initialize
, estoy lugar primordial new
y llamando super
para obtener el comportamiento por defecto de Object#new
. Normalmente definiríamos initialize
en lugar de, este enfoque no se recomienda excepto para cumplir con la solicitud específica en su pregunta.
Cuando pasamos un bloque a una subclase de BlockInit
podemos hacer algo más que simplemente establecer la variable ... básicamente estamos inyectando código en el método initialize
(que estamos evitando escribir). Si también quería un método initialize
que hace otras cosas (como usted ha mencionado en comentarios) se podría añadir a Test
y ni siquiera tiene que llamar super
(ya que nuestros cambios no están en BlockInit#initialize
, en lugar BlockInit.new
)
la esperanza de que es una solución creativa a una solicitud muy específica e intrigante.
La eliminación de un método de inicialización (¿es eso lo que quiso decir?) Hace las cosas difíciles. Al crear nuevos objetos 'Test', ¿debería' name' obtener la misma inicialización cada vez? ¿O debería obtener un valor especificado en código abierto? – DigitalRoss
La motivación sería hacer algo similar a C# - http://msdn.microsoft.com/en-us/library/bb384062.aspx –
¿Hay algo que no le gusta con la solución que propongo? –