为什么“instance.send(:initialize,* args,** kwargs,&block)”只能从Class#new中失败?
我已经坚持了很长一段时间了。 看看这个:
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
类基本上“重新实现”默认的new
方法,以便在initialize
之前进行一些额外的initialize
。
现在,以下工作正常:
t = Test.allocate t.send(:initialize, *[], **{}, &nil)
但是,这不是:
t = Test.new
ArgumentError:参数个数错误(1表示0) from(pry):7:在`initialize'中
它在SuperClass
失败了:
i.send(:initialize, *args, **kwargs, &block)
但显然只有在new
方法中调用它才会失败。 我已经确认args == []
, kwargs == {}
和block == nil
。
有人能解释一下吗?
Ruby版本:
ruby 2.2.3p173(2015-08-18修订版51636)[x86_64-linux]
请不要暗示我没有超载Class.new
。 我知道我可以使用Class.inherited
和Class.append
获得相同的结果。 这个问题只是关于initialize
调用失败的原因。
让我们来看一个更简单的例子,特别是因为问题并不像问题那样具体,它的标题使它看起来像是自己看。
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
( 演示 )。 我可能错了,但我相信这是预期的行为。 然而,它可能是也可能不是真正想要的。 因此,如果你认为双splatting一个空哈希不应该传递一个参数(如**{}
此时),因此工作类似于splatting一个空数组,有一个未解决的问题( Bug#10856 )。 它还提到了这种相对较新的不一致性。
一个简单的*args
将捕获所有参数,包括关键字参数,以防您不需要在new
方法中单独引用kwargs
:
class SuperClass def self.new(*args, &block) i = allocate # Extra instance setup code here i.send(:initialize, *args, &block) i end end