3

如果我有一个 StandardError 实例,消息存储在哪里?

s = StandardError.new("hi")
s.message                          # => "hi"
s.instance_variables               # => []
s.instance_variable_get(:@message) # => nil
s.inspect                          # => "#<StandardError: hi>"
4

3 回答 3

6

此外,请注意并非 Ruby 的所有部分都是用 Ruby 编写的,尤其是对于 Exception 或 StandardError 等非常基础的类。

您可以通过查看Exception类的 message 方法的来源找到答案(单击然后转到 message 方法并使用小放大镜显示来源)。这段代码是 C,而不是 Ruby。

于 2013-02-25T19:38:57.223 回答
3

在对 Ruby 和 C 进行一些调查后,我发现异常类设置了一个名为mesg. 这不能在标准 Ruby 运行时中访问,因为它不是以@.

可以添加一个 Ruby 扩展,它可以让您获取和设置不带前缀的实例变量@。我不知道这可能有多危险。

C 模块:

#include "ruby.h"

static VALUE rb_mIvar;

static VALUE rb_ivar_iv_get(VALUE self, VALUE key) {
  return rb_ivar_get(self, rb_to_id(key));
}

static VALUE rb_ivar_iv_set(VALUE self, VALUE key, VALUE value) {
  return rb_ivar_set(self, rb_to_id(key), value);
}

void Init_ivar() {
  rb_mIvar = rb_define_module("Ivar");
  rb_define_method(rb_mIvar, "ivar_get", rb_ivar_iv_get, 1);
  rb_define_method(rb_mIvar, "ivar_set", rb_ivar_iv_set, 2);
}

红宝石用法:

$:.unshift('.')
require 'ivar'

Object.send(:include, Ivar)

e = StandardError.new("foo")

puts "Error message is: #{e.message}" # => e.message is "foo"

e.ivar_set(:mesg, "bar")

puts "Error message is: #{e.message}" # => e.message is now "bar"

请参阅我用于研究和实验的完整代码的要点:https ://gist.github.com/adamhunter/5041075

于 2013-02-26T19:05:56.077 回答
0

调用返回的消息,该s.message # => "hi"调用又调用该to_s方法。更多信息:Ruby 异常

于 2013-02-25T19:34:44.417 回答