variable objetos manejo lista herencia ejemplos clases clase ruby object new-operator ruby-1.9.3

objetos - variable de clase en ruby



¿Cómo inicializar limpiamente los atributos en Ruby con nuevo? (7)

class Foo attr_accessor :name, :age, :email, :gender, :height def initalize params @name = params[:name] @age = params[:age] @email = params[:email] . . . end

Esto parece una manera tonta de hacerlo. ¿Cuál es una forma mejor / más idiomática de initalizar objetos en Ruby?

Ruby 1.9.3


¿Por qué no simplemente especificar explícitamente una lista real de argumentos?

class Foo attr_accessor :name, :age, :email, :gender, :height def initialize(name, age, email, gender, height) @name = name @age = age @email = email @gender = gender @height = height end end

Esta versión puede contener más líneas de código que otras, pero hace que sea más fácil aprovechar las funciones de lenguaje integradas (por ejemplo, valores predeterminados para argumentos o errores de elevación si se initialize con arity incorrecto).


Para capitalizar la respuesta de Joshua Cheek con un poco de generalización

module Initializable def initialize(params = {}) params.each do |key, value| setter = "#{key}=" send(setter, value) if respond_to?(setter.to_sym, false) end end end class Foo include Initializable attr_accessor :name, :age, :email, :gender, :height end Foo.new name: ''Josh'', age: 456 => #<Foo:0x007fdeac02ecb0 @name="Josh", @age=456>

NB: si se ha utilizado la mezcla de inicialización y necesitamos una inicialización personalizada, simplemente llamaremos a super:

class Foo include Initializable attr_accessor :name, :age, :email, :gender, :height, :handler def initialize(*) super self.handler = "#{self.name} #{self.age}" end end Foo.new name: ''Josh'', age: 45 => #<Foo:0x007fe94c0446f0 @name="Josh", @age=45, @handler="Josh 45">


Puede simplemente iterar sobre las teclas e invocar a los instaladores. Prefiero esto porque atrapará si pasas una clave inválida.

class Foo attr_accessor :name, :age, :email, :gender, :height def initialize params = {} params.each { |key, value| send "#{key}=", value } end end foo = Foo.new name: ''Josh'', age: 456 foo.name # => "Josh" foo.age # => 456 foo.email # => nil


Si recibe un hash como único argumento, ¿por qué no mantenerlo como una variable de instancia? Siempre que necesite un valor, llámelo desde el hash. Puede mantener corto el nombre de la variable de instancia para que pueda ser llamado fácilmente.

class Foo attr_reader :p def initalize p @p = p end def foo do_something_with(@p[:name]) ... end end

Si @p[:name] aún es demasiado largo para usted, puede guardar un proceso como variable de instancia y llamar al valor relevante como @p.(:name) .

class Foo attr_reader :p def initialize p @p = ->x{p[x]} end def foo do_something_with(@p.(:name)) ... end end

O, aún una forma alternativa es definir un método que llame al hash y aplique la clave.

class Foo def initalize p @p = p end def get key @p[key] end def foo do_something_with(get(:name)) ... end end

Si desea establecer los valores, puede definir un método setter y, además, verificar las claves no válidas si lo desea.

class Foo Keys = [:name, :age, :email, :gender, :height] def initalize p raise "Invalid key in argument" unless (p.keys - Keys).empty? @p = p end def set key, value raise "Invalid key" unless Keys.key?(key) @p[key] = value end def get key @p[key] end def foo do_something_with(get(:name)) ... end end


Usar todas las claves de params no es correcto, puede definir nombres poco dispuestos. Creo que debería ser una lista bastante blanca de nombres

class Foo @@attributes = [:name, :age, :email, :gender, :height] @@attributes.each do |attr| class_eval { attr_accessor "#{attr}" } end def initialize params @@attributes.each do |attr| instance_variable_set("@#{attr}", params[attr]) if params[attr] end end end Foo.new({:name => ''test''}).name #=> ''test''


Foo = Struct.new(:name, :age, :email, :gender, :height)

Esto es suficiente para una clase completamente funcional. Manifestación:

p Foo.class # Class employee = Foo.new("smith", 29, "[email protected]", "m", 1.75) #create an instance p employee.class # Foo p employee.methods.sort # huge list which includes name, name=, age, age= etc


def initialize(params) params.each do |key, value| instance_variable_set("@#{key}", value) end end