分配实例变量的快捷方式

时间:2014-11-30 16:25:09

标签: ruby instance-variables

我跟随Codecademy的Ruby课程,大约85%完成了。

它一遍又一遍地要求你创建一个类并传入一些参数并使它们成为实例变量,例如:

class Computer
    def initialize(username, password)
        @username = username
        @password = password
    end
end

每次,它都会要求您生成与传入的参数完全相同的实例变量。

这让我想知道是否有一种Ruby方法可以自动处理这种情况,无需每次都自己输入。

我知道你可以做到

class Computer
    def initialize(username, password)
        @username, @password = username, password
    end
end

但这种打字几乎没有那么简单。

我做了一些搜索,发现你可以创建一组“getter”'使用attr_reader喜欢

class Song
    attr_reader :name, :artist, :duration
end

aSong = Song.new("Bicylops", "Fleck", 260)
aSong.artist # "Fleck"
aSong.name # "Bicylops"
aSong.duration # 260

但据我所知,这并不是我真正想要的。我没有尝试自动创建getter和/或setter。我正在寻找的将是这样的

class Person
    def initialize(name, age, address, dob) #etc
        # assign all passed in parameters to equally named instance variables
        # for example
        assign_all_parameters_to_instance
        # name, age, address and dob would now be accessible via
        # @name, @age, @address and @dob, respectively
    end
end

我做了一些搜索 ruby​​快捷方式,用于分配实例变量等但无法找到答案。

这可能吗?如果是这样,怎么样?

4 个答案:

答案 0 :(得分:6)

Person = Struct.new(:name, :artist, :duration) do
  # more code to the Person class
end

您的另一个选择是传递变量的Hash /关键字,并使用类似ActiveModel :: Model的东西 https://github.com/rails/rails/blob/master/activemodel/lib/active_model/model.rb#L78-L81

def initialize(params={})
  params.each do |attr, value|
    self.instance_variable_set("@#{attr}", value)
  end if params
end

答案 1 :(得分:1)

首先,你的attr_reader集的第二个块将不起作用。因为您为默认的initialize方法提供了3个参数,它接受0个参数。

回答你的问题是否定的,没有这样的方法,除非你打算用元编程自己定义它。

答案 2 :(得分:1)

assign_all_parameters_to_instance无法以您希望的方式存在。它需要访问其调用者的局部变量或参数,这是一件非常尴尬的事情,并且违反了方法封装。

但是,您可以生成合适的initialize方法:

class Module
  private def trivial_initializer(*args)
    module_eval(<<-"HERE")
      def initialize(#{args.join(', ')})
        #{args.map {|arg| "@#{arg} = #{arg}" }.join("\n")}
      end
    HERE
  end
end

class Computer
  trivial_initializer :username, :password
end

Computer.new('jwm', '$ecret')
# => #<Computer:0x007fb3130a6f18 @username="jwm", @password="$ecret">

答案 3 :(得分:0)

我使用了这个https://www.safaribooksonline.com/library/view/ruby-cookbook/0596523696/ch10s09.html,它对我来说很好。

我只需将eval(var, binding)替换为eval(var.to_s, binding)

最后:

class Object
  private
  def set_instance_variables(binding, *variables)
    variables.each do |var|
      instance_variable_set("@#{var}", eval(var.to_s, binding))
    end
  end
end

class RGBColor
  def initialize(red=0, green=0, blue=0)
    set_instance_variables(binding, *local_variables)
  end
end

RGBColor.new(10, 200, 300)
# => #<RGBColor:0xb7c22fc8 @red=10, @blue=300, @green=200>