ruby:质量初始化实例变量

是否有一种简单的方法来批量分配实例变量

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 

我可以循环/遍历初始化参数并自动分配吗?

如果你想要特定的变量,那么不是真的。 在这里使用reflection,即使它可用,也会很麻烦。

你在这里得到的是最微不足道的案例。 通常你会看到看起来更像这样的代码:

 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 

初始化程序是您可以进行任何必要的转换和validation的地方。 如果某些参数需要是某些值,那么您将对其进行测试,针对错误raiseexception,等等。 在最小的情况下,您在这里重复的代码经常被扩展和扩充,因此没有可能的通用解决方案。

这导致代码如下:

 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 

如果你真的不关心你正在考虑哪些参数,那么你可以使用新的关键字参数说明符**在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 

如果您经常看到很多这些参数被传递,您可能想要评估是否创建某种类似结构的对象并将其传递出来可能是一个更好的计划。 这取决于您的代码如何工作。

@tadman已经提供了一个很好的答案,但是还有一个:如果你愿意免除命名参数,你可以这样做:

 def initialize(*args) @title, @label_left, @label_right, @color_set, *nada = args fail "Too many arguments" unless nada.empty? end 

[更新:修复了代码,根据@sawa给出的评论]。