当对象#初始化被重载时,与 Ruby 中的 IRB 输出混淆



当类定义没有给出'初始化'方法时,我实际上想看到什么,然后你说的类应该调用"Object#initialize",在这里我试图自定义并查看它是否已被调用。通过这种方法,我得出了一个结论(尽管这是错误的(,当我输入"ob = A .new"时,是的,我可以重载Object#initialize方法。但一切都以以下例外告终。然后我想我在定制中做错了什么。所以我尝试在异常块中创建对象创建,当我输入"开始"并按"ENTER"时 - 我遇到了同样的错误。

>>  class A
>>  def Object.new initialize
>>   p "hi"
>>   rescue
>>  end
>>  end
=> nil
>>  begin # <~~~ Here I have pressed on ENTER
"hi"  #<~~~~ How was it print out?
/usr/lib/ruby/1.9.1/irb/ruby-token.rb:94:in `Token': undefined method `set_backtrace' for "hi":String (NoMethodError)
    from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:348:in `block in lex_init'
    from /usr/lib/ruby/1.9.1/irb/slex.rb:236:in `call'
    from /usr/lib/ruby/1.9.1/irb/slex.rb:236:in `match_io'
    from /usr/lib/ruby/1.9.1/irb/slex.rb:221:in `match_io'
    from /usr/lib/ruby/1.9.1/irb/slex.rb:75:in `match'
    from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:286:in `token'
    from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:262:in `lex'
    from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:233:in `block (2 levels) in each_top_level_statement'
    from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `loop'
    from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `block in each_top_level_statement'
    from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `catch'
    from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `each_top_level_statement'
    from /usr/lib/ruby/1.9.1/irb.rb:155:in `eval_input'
    from /usr/lib/ruby/1.9.1/irb.rb:70:in `block in start'
    from /usr/lib/ruby/1.9.1/irb.rb:69:in `catch'
    from /usr/lib/ruby/1.9.1/irb.rb:69:in `start'
    from /usr/bin/irb:12:in `<main>'
@ubuntu:~$

现在我的问题是——

  • "嗨"是如何打印的?

  • 上面打印的错误的原因是什么?

  • 如果不允许这样的initialize定义,那么为什么在我以类定义结束之后没有出现错误?

编辑

根据@casper我在下面尝试:

>> def Object.new
>> p "hi"
>> end
=> nil
>> begin
/usr/lib/ruby/1.9.1/irb/ruby-token.rb:96: stack level too deep (SystemStackError)

但这里没有"hi"打印回来。

那么,是什么让"嗨"在第一种情况下打印回来呢?

你到底想做什么?你刚刚重新定义了Object.new,所以你让一切都变得混乱也就不足为奇了。

你基本上可以得到同样的效果,只需:

>> def Object.new
>> end
>> [press enter]
KABOOM

打印"hi"的原因是有人刚刚调用了Object.new,可能是irb REPL循环,它期望一个对象,但相反,它得到了gobledygook。

你也可以试试这个:

def Object.new *args
  p args
end

你会看到有趣的东西。但是,在那之后您将无法退出 irb 或对其进行任何有用的操作。再说一遍:你刚刚打破了Object.

为了理解它,你应该阅读这个:
在 Ruby 中,"new"和"initialize"之间有什么关系?初始化时如何返回 nil?

然后你可以试试这个:

class Object
  class << self
    alias :old_new :new
  end
end

现在您可以执行以下操作:

def Object.new *args
   p args
   old_new *args
end

这不会破坏new,因为您仍在调用它的旧版本。但是,您现在每次有人打电话给new时都会打印出东西。

最新更新