Ruby “为什么?”;发送(:initialize,*args,**kwargs,&;block)";仅在类内失败#新?

Ruby “为什么?”;发送(:initialize,*args,**kwargs,&;block)";仅在类内失败#新?,ruby,ruby-2.2,Ruby,Ruby 2.2,我已经在这上面呆了很长时间了。看看这个: 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

我已经在这上面呆了很长时间了。看看这个:

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
然而,这并不是:

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

有人能解释这一点吗


Ruby版本:

ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux] ruby 2.2.3p173(2015-08-18修订版51636)[x86_64-linux]
请不要建议我不要超载
类。新建
。我知道我可以使用
Class.inherited
Class.append
获得相同的结果。这个问题只是关于调用
initialize
失败的原因。

一个简单的
*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

一个简单的
*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

让我们看一个更简单的例子,特别是因为问题没有问题那么具体,问题的标题让问题看起来像,但你自己看

def m   # takes no arguments
end
m(**{}) # no argument is passed
h = {}
m(**h)  # an argument is passed => ArgumentError is raised
这种不一致性是在2.2.1中由一个旨在修复涉及
**{}
()的分段错误的提交引入的。提交特殊情况
**{}
以不传递参数。其他方式,如
**Hash.new
h={}**h
仍将空哈希作为参数传递


以前的版本始终会引发
ArgumentError
()。我可能错了,但我相信这是我的本意。然而,它可能是也可能不是真正想要的。因此,如果您认为双重散列空散列不应该传递参数(比如现在的
**{}
),因此其工作原理类似于散列空数组,那么关于这一点,有一个公开的问题()。它还提到了这种相对较新的不一致性。

让我们看一个更简单的例子,特别是因为问题没有问题那么具体,问题的标题让它看起来像,但你自己看

def m   # takes no arguments
end
m(**{}) # no argument is passed
h = {}
m(**h)  # an argument is passed => ArgumentError is raised
这种不一致性是在2.2.1中由一个旨在修复涉及
**{}
()的分段错误的提交引入的。提交特殊情况
**{}
以不传递参数。其他方式,如
**Hash.new
h={}**h
仍将空哈希作为参数传递



以前的版本始终会引发
ArgumentError
()。我可能错了,但我相信这是我的本意。然而,它可能是也可能不是真正想要的。因此,如果您认为双重散列空散列不应该传递参数(比如现在的
**{}
),因此其工作原理类似于散列空数组,那么关于这一点,有一个公开的问题()。它还提到了这种相对较新的不一致性。

它似乎与
i.send(:initialize,*args,**kwargs,&block)一起工作。
更改为
i.send(:initialize,*args,&block)
@CarySwoveland。就我所见,它的行为似乎是相同的。原因似乎是
**kwargs
将零个或多个关键字参数转换为散列,因此如果没有,则会得到一个空散列,这当然是一个参数。您可以很容易地测试它。@CarySwoveland但是
send(:initialize,*[],***{},&nil)
在其他地方工作,没有参数被发送到
initialize
。这个问题只发生在
类#new
方法中。我们发现错误了吗?@cremno So 2.2.0仍然具有正确的行为,而更高版本由于延迟的segfault修复而具有错误的行为:PIt似乎与
i.send(:initialize,*args,**kwargs,&block)一起工作。
更改为
i.send(:initialize,*args,&block)
@CarySwoveland。就我所见,它的行为似乎是相同的。原因似乎是
**kwargs
将零个或多个关键字参数转换为散列,因此如果没有,则会得到一个空散列,这当然是一个参数。您可以很容易地测试它。@CarySwoveland但是
send(:initialize,*[],***{},&nil)
在其他地方工作,没有参数被发送到
initialize
。这个问题只发生在
类#new
方法中。我们发现错误了吗?@cremno So 2.2.0仍然具有正确的行为,而更高版本由于延迟的segfault修复而具有错误的行为:PI不知道
新的
,因为实例方法是一件事。。。现在我真的很困惑所有这些方法是如何结合在一起的。为什么它既可以是类方法又可以是实例方法呢?我想类方法内部只是为了方便起见调用实例方法
new
,因此您可以正确地访问
initialize
。红宝石魔术;-)尽管如此,我如何从已经分配的实例中分配一个新实例,并返回该实例?这对我来说仍然没有意义,我只是在Ruby 2.2.3中测试了这一点,而且从未调用过
类#new
:SIt对我来说也没有意义,我必须为给你指出错误的方向而道歉。这篇博文是错误的,实际上你需要重写
初始化
并使用
发送
。不过,我回答的第二部分仍然有效。编辑…我不知道
new
,因为实例方法是一件事。。。现在我真的很困惑所有这些方法是如何结合在一起的。为什么它既可以是类方法又可以是实例方法呢?我想类方法内部只是为了方便起见调用实例方法
new
,因此您可以正确地访问
initialize
。红宝石魔术;-)尽管如此,我如何从已经分配的实例中分配一个新实例,并返回该实例?这对我来说仍然没有意义,我只是在Ruby 2.2.3中测试了这一点,而
Class#new
是n
def m   # takes no arguments
end
m(**{}) # no argument is passed
h = {}
m(**h)  # an argument is passed => ArgumentError is raised