我跟随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快捷方式,用于分配实例变量等但无法找到答案。
这可能吗?如果是这样,怎么样?
答案 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>