0

我已经坚持了很长一段时间了。看看这个:

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.

现在,以下工作正常:

t = Test.allocate
t.send(:initialize, *[], **{}, &nil)

但是,这不会:

t = Test.new
ArgumentError:参数数量错误(1 代表 0)
从(撬):7:在“初始化”

它在这条线上失败SuperClass

i.send(:initialize, *args, **kwargs, &block)

但显然只有在方法中调用它才会失败new。我已经确认args == [],kwargs == {}block == nil

有人能解释一下吗?


红宝石版本:

ruby 2.2.3p173(2015-08-18 修订版 51636)[x86_64-linux]

请不要暗示我不要超载Class.new。我知道我可以使用Class.inheritedandClass.append来获得相同的结果。这个问题只是关于为什么调用initialize失败。

4

2 回答 2

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 中由旨在修复涉及**{}错误 #10719)的分段错误的提交引入的。**{}不传递参数的提交特殊情况。其他方式像**Hash.new并且h={};**h仍然将空哈希作为参数传递。

以前的版本不断提高ArgumentError演示)。我可能是错的,但我相信这是预期的行为。然而,它可能是也可能不是真正想要的。因此,如果您认为双喷空散列不应该传递参数(就像**{}现在一样),因此与喷空数组类似,则存在一个未解决的问题(Bug #10856)。它还提到了这种相对较新的不一致。

于 2015-10-13T12:27:16.253 回答
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
于 2015-10-13T08:18:26.370 回答