是否有一种简单的方法来批量分配实例变量
def initialize(title: nil, label_left: nil, label_right: nil, color_set: nil)
@title = title
@label_left = label_left
@label_right = label_right
@color_set = color_set
end
我可以循环/遍历初始化参数并自动分配吗?
答案 0 :(得分:9)
如果你想要特定的变量,那么不是真的。在这里使用反射,即使它可用,也会有麻烦。
你在这里得到的是最微不足道的案例。通常你会看到看起来更像这样的代码:
def initialize(title: nil, label: nil, label_width: nil, color_set: nil)
@title = title.to_s
@label = label_left.to_s
@label_width = label_width.to_i
@color_set = MyRGBConverter.to_rgb(color_set)
end
初始化程序是您可以进行任何必要的转换和验证的地方。如果某些参数需要是某些值,那么您将对其进行测试,raise
出现错误异常,等等。在最小的情况下,您在这里重复的代码经常被扩展和扩充,因此没有通用的解决方案。
这导致了这样的代码:
def initialize(title: nil, label: nil, label_width: nil, color_set: nil)
@title = title.to_s
unless (@title.match(/\S/))
raise "Title not specified"
end
@label = label_left.to_s
unless (@label.match(/\A\w+\z/))
raise "Invalid label #{@label.inspect}"
end
@label_width = label_width.to_i
if (@label_width <= 0)
raise "Label width must be > 0, #{@label_width} specified."
end
@color_set = MyRGBConverter.to_rgb(color_set)
end
如果您真的不关心您正在考虑哪些参数,那么您可以使用新的 keyword-arguments 说明符**
在Ruby 2.3中执行此操作:
def initialize(**options)
options.each do |key, value|
instance_variable_set("@#{key}", value)
end
end
请注意,如果这些值是用户提供的,则存在潜在危险,因此您可能希望以某种方式将其列入白名单:
VALID_OPTIONS = [ :title, :label_left, :label_right, :color_set ]
def initialize(**options)
options.each do |key, value|
raise "Unknown option #{key.inspect}" unless (VALID_OPTIONS.include?(key))
instance_variable_set("@#{key}", value)
end
end
如果您经常看到很多这些参数被传入,您可能想要评估是否创建某种类似结构的对象并将其传递可能是一个更好的计划。这取决于代码的工作方式。
答案 1 :(得分:1)
@tadman已经提供了一个很好的答案,但是还有一个:如果你愿意免除命名参数,你可以这样做:
def initialize(*args)
@title, @label_left, @label_right, @color_set, *nada = args
fail "Too many arguments" unless nada.empty?
end
[更新:修正了代码,根据@sawa给出的评论]。