2016-11-21 81 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