为什么“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.inheritedClass.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.newh={};**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