简体   繁体   English

Ruby为什么不自动执行to_s?

[英]Why doesn't Ruby automatically execute to_s?

I have an author class: 我有一个作家班:

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

Defining to_s allows me to do puts Author.first , but not puts Author.first.rjust(10) : 定义to_s允许我执行puts Author.first ,但不能执行puts Author.first.rjust(10)

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

Wouldn't it be better if Ruby automatically tried to_s before the string method in cases like this? 在这种情况下,如果Ruby在string方法之前自动尝试to_s会更好吗? Is there any way to get this behavior? 有什么办法可以得到这种行为?

First off, no, it wouldn't. 首先,不,不是。 I don't want ruby to just say "Hey, maybe this is a string method, let me see if I can run it after running to_s " on an arbitrary object. 我不想让ruby仅仅说“嘿,也许这是一个字符串方法,让我看看是否可以在任意对象上运行to_s之后运行它”。 That being said, there are two solutions to what you want to do: 话虽这么说,您有两种解决方案:

If you want to say "On any Author instance, if someone calls a method that it doesn't have, but that String does, then it should magically call to_s ", then do this: 如果要说“在任何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

If you want to say " rjust on anything that isn't a String should mean calling to_s first", then: 如果你想说“ rjust上任何不是一个字符串应该是指调用to_s第一”,则:

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

(Repeat with other methods as desired; note that this allows you to do things like 86.rjust(10) ; whether that's a good thing or not may be a matter of taste) (根据需要使用其他方法重复;请注意,这允许您执行类似86.rjust(10) ;这是否是一件好事,可能86.rjust(10)您的口味)

Wouldn't it be better if Ruby automatically tried to_s before the string method in cases like this? 在这种情况下,如果Ruby在string方法之前自动尝试to_s会更好吗?

You're heading down a slippery slope by asking for a language to "just do what I mean (most of the time)." 您要求一种语言“在大多数时间里都按照我的意思行事”,这是一条滑坡。 While it might make sense in many cases, it's bound to foul things up around the edges. 尽管在许多情况下这可能很有意义,但势必会使边缘的事情变得肮脏。 In your case, who's to say that rjust isn't a method defined on Author (or one of its superclasses). 在您的情况下,谁说rjust并不是在Author(或其超类之一)上定义的方法。

Actually... there IS a method that would do something vaguely similar to this: to_str 实际上...有一种方法可以执行与此类似的操作: to_str

However, it still wouldn't be called implicitly for this particular case. 但是,在这种情况下仍然不会隐式调用它。 The existence of a to_str method in Ruby is effectively equivalent to saying, "Any method that would normally take a String as a parameter may implicitly convert this object to a String by calling the to_str method." Ruby中存在to_str方法实际上等效于说:“通常将String作为参数的任何方法都可以通过调用to_str方法将该对象隐式转换为String。” Most methods in the standard library will attempt to use this technique to coerce to String, and a lot of 3rd party libraries do as well. 标准库中的大多数方法都将尝试使用此技术来强制转换为String,许多第三方库也是如此。

In the example you gave, however, it would be absolutely inappropriate for Ruby to detect that an unhandled message was String-like and convert. 但是,在您给出的示例中,对于Ruby而言,检测未处理的消息类似于String并进行转换绝对是不合适的。 This would lead to all kinds of errors, bugs, and general misbehavior in a lot of non-String related code, especially any of the code out there like Builder that relies on the normal missing method behavior. 这将导致许多与String不相关的代码中的各种错误,错误和一般的不当行为,尤其是像Builder这样依赖正常的方法缺失行为的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM