【问题标题】:ruby: mass initializing instance variablesruby:批量初始化实例变量
【发布时间】:2017-04-05 10:31:25
【问题描述】:

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

  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

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

【问题讨论】:

    标签: ruby-on-rails ruby class object constructor


    【解决方案1】:

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

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

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

    【讨论】:

    • 您需要将其更改为*nadaunless nada.empty? 以使其按预期工作。 Ruby 爱好者更喜欢简单地写成*
    • 感谢您指出错误。我会在我的回答中修复它。您能否详细说明您评论的第二部分?在这种情况下,你怎么能使用唯一的*
    • 对不起,你需要*nada,就像你做的那样。顺便说一句,没有empty 方法。
    • @sawa:你是一个细心的读者,就像我是一个草率的程序员一样。固定。
    【解决方案2】:

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

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

    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 中使用新的 keyword-arguments 说明符 **

    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
    

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

    【讨论】:

      猜你喜欢
      • 2011-06-21
      • 2011-12-25
      • 2012-06-15
      • 2011-03-18
      • 2010-11-26
      • 1970-01-01
      • 1970-01-01
      • 2017-10-23
      • 2014-09-14
      相关资源
      最近更新 更多