如何用Ruby干净地初始化Ruby中的属性?

B S*_*ven 29 ruby object new-operator ruby-1.9.3

class Foo
  attr_accessor :name, :age, :email, :gender, :height

  def initalize params
    @name = params[:name]
    @age = params[:age]
    @email = params[:email]
    .
    .
    .
  end
Run Code Online (Sandbox Code Playgroud)

这似乎是一种愚蠢的做法.在Ruby中初始化对象的更好/更惯用的方法是什么?

Ruby 1.9.3

Jos*_*eek 41

您可以迭代密钥并调用setter.我更喜欢这个,因为如果你传递了一个无效的密钥,它会被捕获.

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
Run Code Online (Sandbox Code Playgroud)


Zac*_*emp 17

def initialize(params)
  params.each do |key, value|
    instance_variable_set("@#{key}", value)
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 我一般不喜欢这个,但是如果你打算使用它,至少要调用setter而不是设置实例变量.如果你使用ivars弄乱了变量的名称,你就不会知道它,但是使用方法,你会得到一个NoMethodError. (5认同)

Vad*_*rov 12

通过一些概括来充分利用Joshua Cheek的答案

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>
Run Code Online (Sandbox Code Playgroud)

注意如果已经使用了初始化混合,我们需要自定义初始化,我们只需要调用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"> 
Run Code Online (Sandbox Code Playgroud)


ste*_*lag 6

Foo = Struct.new(:name, :age, :email, :gender, :height)
Run Code Online (Sandbox Code Playgroud)

这对于一个功能齐全的课程来说足够了.演示:

p Foo.class # Class

employee = Foo.new("smith", 29, "smith@foo.com", "m", 1.75) #create an instance
p employee.class # Foo
p employee.methods.sort # huge list which includes name, name=, age, age= etc
Run Code Online (Sandbox Code Playgroud)