为什么Ruby不自动执行to_s?

Tom*_*man 0 ruby string metaprogramming

我有一个作者类:

class Author < ActiveRecord::Base
  def to_s
    name
  end
end
Run Code Online (Sandbox Code Playgroud)

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

NoMethodError: undefined method `rjust' for #<Author:0x21eb5d4>
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*tin 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
Run Code Online (Sandbox Code Playgroud)

如果你想说" rjust关于任何不是字符串的东西应该意味着to_s先叫",那么:

class Object
  def rjust(*a)
    to_s.rjust(*a)
  end
end
Run Code Online (Sandbox Code Playgroud)

(根据需要重复其他方法;请注意,这可以让您做一些事情86.rjust(10);这是否是好事可能是品味问题)

  • 那个`super.method_missing(s,*a)`是不正确的.它应该只是`super`,它使用相同的参数调用超类的方法版本.在Ruby中,super就像一个方法而不是一个接收器. (3认同)