2

我想创建一个需要值的函数,除非它已经创建了一个实例值。但是,我不想nil默认设置参数,而是希望它优雅地知道它是否需要接受参数。例如,

def config(c)
    @config ||= c
end

@config如果我调用它会返回,但是ArgumentError当我尝试在没有参数的情况下调用它时会给出。如果实例变量存在,我可以使函数不需要参数吗?

4

3 回答 3

9

Ruby 没有提供任何工具来做到这一点,但为什么不自己提出 ArgumentError 像这样:

def config(c = nil)
  raise ArgumentError unless c || @config
  @config ||= c
end

或者,Ruby 2.0 提供了类似这样的关键字参数:

class A
  def config c: (@config or raise ArgumentError)
    @config = c
  end
end

a = A.new
a.config        #=> ArgumentError
a.config(c: 2)  #=> 2
a.config        #=> 2

当然,也许您真正应该做的只是使用正常的设置方法(即def config=(value) ...)或简单地使用attr_accessor :config. 也就是说,至少在您的基本示例中,这是最惯用的方法。

于 2013-07-10T02:36:23.390 回答
3

我不确定为什么您需要避免将参数默认为 nil,但要获得您指定的功能:

“如果没有传入参数并且未设置实例变量,则需要引发参数错误,但如果设置了实例变量,则允许在没有参数的情况下调用它。”

这将起作用:

def config(c=nil)
  raise ArgumentError if c.nil? && @config.nil?
  @config ||= c
end

是的,我将参数默认为 nil,这是您要求避免的,但如果参数为 nil,那么如果未设置 @config 并且如果设置了 @config,则我们会短路并引发错误,如果参数为 nil,因为下一行将只返回 @config。

于 2013-07-10T02:35:22.517 回答
-1

您可以*在参数之前使用:

def config(*c)
    @config ||= c
end

但是请注意,c如果您运行,您现在将获得多个值:config('hi', 'hello')除此之外它还可以工作。

于 2013-07-10T02:23:24.327 回答