我已经坚持了很长一段时间了。看看这个:
class SuperClass
def self.new(*args, **kwargs, &block)
i = allocate()
# Extra instance setup code here
i.send(:initialize, *args, **kwargs, &block)
return i
end
end
class Test < SuperClass
def initialize
puts "No args here"
end
end
班级SuperClass
基本上&#34;重新实施&#34;默认的new
方法,以便在initialize
之前进行一些额外的初始化。
现在,以下工作正常:
t = Test.allocate
t.send(:initialize, *[], **{}, &nil)
然而,这不是:
t = Test.new
ArgumentError: wrong number of arguments (1 for 0) from (pry):7:in `initialize'
SuperClass
i.send(:initialize, *args, **kwargs, &block)
但显然只有在new
方法中调用它才会失败。我已确认args == []
,kwargs == {}
和block == nil
。
有人能够解释这个吗?
Ruby版本:
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
请不要建议我不要超载Class.new
。我知道我可以使用Class.inherited
和Class.append
获得相同的结果。这个问题只是关于调用initialize
失败的原因。
答案 0 :(得分:4)
让我们来看一个更简单的例子,特别是因为这个问题并不像问题那样具体,而且它的标题看起来像是看起来像你自己一样。
def m # takes no arguments
end
m(**{}) # no argument is passed
h = {}
m(**h) # an argument is passed => ArgumentError is raised
这种不一致性是在2.2.1中通过旨在修复涉及**{}
(Bug #10719)的分段错误的提交引入的。提交特殊情况**{}
不传递参数。像**Hash.new
和h={};**h
这样的其他方式仍然会将空哈希作为参数传递。
以前的版本不断提升ArgumentError
(demo)。我可能错了,但我相信这是预期的行为。然而,它可能是也可能不是实际想要的。因此,如果你认为双splatting一个空哈希不应该传递一个参数(如此时的**{}
),因此类似于splatting一个空数组,有一个公开的问题({{3 }})。它还提到了这种相对较新的不一致。
答案 1 :(得分:0)
如果您不需要在*args
方法中单独引用kwargs
,则简单的new
将捕获包括关键字参数在内的所有参数:
class SuperClass
def self.new(*args, &block)
i = allocate
# Extra instance setup code here
i.send(:initialize, *args, &block)
i
end
end