加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Ruby捕获NoMethodError并从发生异常的地方继续执行

发布时间:2020-12-17 03:02:04 所属栏目:百科 来源:网络整理
导读:在 Ruby中,我想捕获在另一个对象中的对象上生成的NoMethodError,然后将一些值返回到引发异常的位置并继续执行.有现成的方法吗? 我想出的最好的是: class Exception attr_accessor :continuationendclass Outer def hello puts "hello" end class Inner def
在 Ruby中,我想捕获在另一个对象中的对象上生成的NoMethodError,然后将一些值返回到引发异常的位置并继续执行.有现成的方法吗?

我想出的最好的是:

class Exception
  attr_accessor :continuation
end

class Outer
  def hello
    puts "hello"
  end

  class Inner
    def world
      puts "world"
    end
    def method_missing(method,*args,&block)
      x = callcc do |cc|
        e = RuntimeError.exception(method)
        e.continuation = cc
        raise e
      end
      return x
    end
  end

  def inner(&block)
    inner = Inner.new
    begin
      inner.instance_eval(&block)
    rescue => e
      cc = e.continuation
      cc.call(hello())
    end
    inner
  end
end

o = Outer.new
o.inner do
  hello
  world
end

这打印

hello
world

有没有更好的方法来使用Ruby现有的元编程库?基本上,我不确定callcc是否会继续存在.

谢谢.

解决方法

这个简单的方法怎么样:

class Outer
  def hello
    puts "hello"
  end

  class Inner
    def initialize outer
      @outer = outer
    end

    def world
      puts "world"
    end

    def method_missing(method,&block)
      @outer.send(method,&block)
    rescue NoMethodError # you can also add this
      puts "#{method} is undefined in both inner and outer classes"
    end
  end

  def inner(&block)
    inner = Inner.new self
    inner.instance_eval(&block)
    inner
  end
end

o = Outer.new
o.inner do
  hello
  cruel
  world
end

会打印

hello
cruel is undefined in both inner and outer classes
world

在这种情况下,如果内部类没有定义所需的方法,则使用Object#send将其委托给外部类.您可以在method_missing中捕获NoMethodError,以便在外部类未定义委托方法时控制情境.

UPDATE
您还可以使用光纤来解决问题:

class Outer
    def hello
        puts "hello"
    end

    class Inner
        def world
            puts "world"
        end

        def method_missing(method,&block)
            Fiber.yield [method,args,block] # pass method args to outer
        end
    end

    def inner(&block)
        inner = Inner.new
        f = Fiber.new { inner.instance_eval(&block) }
        result = nil # result for first fiber call does not matter,it will be ignored
        while (undef_method = f.resume result) # pass method execution result to inner
            result = self.send(undef_method[0],*undef_method[1],&undef_method[2])
        end
        inner
    end
end

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读