0

我有这样的课:

class MyClass < BasicObject
  class Error < ::NoMethodError
  end
end

我有这个:

def method_missing(....)
  raise Error
end

SystemStackError: stack level too deep当我调用缺少的方法时,我得到了。我想一些递归正在进行,但我不明白为什么以及发生了什么。

你能帮我么?

附言

class MyClass 
  class Error < NoMethodError
  end
end

这很好用。

4

1 回答 1

2
class MyClass < BasicObject
  class Error < ::NoMethodError
     def method_missing(....)
       raise Error
     end
  end
end

p MyClass.superclass # => BasicObject
p method(:raise).owner # => Kernel

现在Kernel不存在于MyClass类的祖先链中。这样当你raise在方法内部调用时method_missing,又会再次调用method_missing方法(因为raise不是类的方法MyClass,也不是所有者Kernel混入Myclass,所以raise方法查找失败,导致重复调用method_missing。因此导致错误为SystemStackError: stack level too deep。我在这里尝试重新创建您所面临的场景,如下所示:

class Foo < BasicObject
   def method_missing(name,*args)
       p "hi"
   end
end

Foo.new.baz
# stack level too deep (SystemStackError)

这里也是同理。没有Foo#baz方法,所以method_missing叫第一次。现在在里面method_missing,我试图调用另一种方法,即类方法Kernel。现在Kernel既不混BasicObject,也不混Foo。所以方法查找失败,method_missing由于调用方法而重复调用Kernel#p,导致错误。要解决此问题,我将执行以下操作:

class Foo < BasicObject
  include ::Kernel
   def method_missing(name,*args)
       p "hi"
   end
end

Foo.new.baz # => "hi"

希望你现在明白了。

于 2013-11-12T12:52:24.677 回答