0

我有一个作者类:

class Author < ActiveRecord::Base
  def to_s
    name
  end
end

定义to_s允许我做puts Author.first,但不是puts Author.first.rjust(10)

NoMethodError: undefined method `rjust' for #<Author:0x21eb5d4>

to_s在这种情况下,如果 Ruby 在 string 方法之前自动尝试,不是更好吗?有没有办法得到这种行为?

4

4 回答 4

18

首先,不,它不会。我不希望 ruby​​ 只是说“嘿,也许这是一个字符串方法,让我看看我是否可以在运行后运行它to_s” 在任意对象上。话虽如此,您想要做的事情有两种解决方案:

如果您想说“在任何Author情况下,如果有人调用了它没有的方法,但String确实如此,那么它应该神奇地调用to_s”,然后执行以下操作:

class Author < ActiveRecord::Base
  def to_s
    name
  end

  def method_missing(s, *a)
    x = to_s
    if x.respond_to? s then
      return x.send(s, *a)
    else
      super
    end
  end
end

如果你想说“rjust在任何不是字符串的东西上应该意味着to_s首先调用”,那么:

class Object
  def rjust(*a)
    to_s.rjust(*a)
  end
end

(根据需要使用其他方法重复;请注意,这允许您执行类似的操作86.rjust(10);这是否是一件好事可能是个人喜好问题)

于 2009-06-13T23:40:43.040 回答
2

在这种情况下,如果 Ruby 在 string 方法之前自动尝试 to_s 会不会更好?

通过要求一种语言“只做我的意思(大部分时间)”,你正在走下一个滑坡。虽然在许多情况下它可能是有意义的,但它必然会在边缘搞砸。在您的情况下,谁能说rjust不是在 Author (或其超类之一)上定义的方法。

于 2009-06-14T00:36:05.420 回答
2

查看 ruby​​ 对委托和方法转发的支持

于 2009-06-17T15:41:00.923 回答
1

实际上......有一种方法可以做一些与此类似的事情:to_str

但是,对于这种特殊情况,它仍然不会被隐式调用。Ruby 中方法的存在to_str实际上等同于说:“任何通常将 String 作为参数的方法都可以通过调用该to_str方法隐式将此对象转换为 String。” 标准库中的大多数方法都会尝试使用这种技术来强制转换为 String,许多 3rd 方库也这样做。

但是,在您给出的示例中,Ruby 检测到未处理的消息类似于字符串并进行转换是绝对不合适的。这将导致许多非字符串相关代码中的各种错误、错误和一般不当行为,尤其是像 Builder 这样依赖于正常缺失方法行为的任何代码。

于 2009-06-15T18:15:12.537 回答