2016-11-21 68 views
2

是否有一个简单的方法来批量指定实例变量红宝石:质量初始化实例变量

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 

我可以循环/通过初始化参数进行迭代,并自动分配?

回答

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 

如果你真的不关心你正在服用的参数,那么你可以用新的关键字参数做到这一点用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

@tadman已经提供了一个很好的答案,但这里是一个多:如果你愿意与命名参数来分配,你可以做这样的:

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

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

+1

您需要将其更改为'* nada','除非nada.empty?'使其按照预期工作。 Rubyists喜欢简单地写成'*'。 – sawa

+0

感谢您指出错误。我会在我的答案中解决它。你能否详细说明你评论的第二部分?在这种情况下,你怎么能使用一个唯一的'*'? – user1934428

+0

对不起,你需要'* nada'就像你一样。顺便说一句,没有'空'的方法。 – sawa