Ruby to_s,to_str 和 inspect

hooopo for Shopper+ · 2012年06月23日 · 最后由 greister 回复于 2015年09月18日 · 15810 次阅读

to_s 和 to_str 的区别:http://rubylution.herokuapp.com/topics/17 to_s 和 inspect 的区别:http://rubylution.herokuapp.com/topics/19

原来如此,谢谢分享。

没看。不过这些早就了解啦

#2 楼 @zw963 写给不了解的:-)

to_s 和 to_str 这些感觉有些麻烦,有些怀疑是否真有区别的必要

#4 楼 @jjym 其实这里面有细微差别的。并且这样的差别并不影响初级使用者,但是高阶一点的使用者却可以用的很顺手。

to_s means "You can turn me into a string", while to_str means "For all intents and purposes, I am a string".

to_s 是表示把一个对象的字符串状态呈现出来,不管结果如何。只要得到字符串的状态。 所以普通对象一般 to _s 后都是这样"# < A:0x9c5ce8 >",几乎没有意义。

而一般对象是没有定义 to_str 的,如果定义了就表示这个对象能完美的呈现字符串状态(比如 Path 对象,Rails.env),在与字符串做相关操作(join / gsub/ <<等),就会优先调用 to_str。

ruby-1.9.3-p0 :050 > Rails.env.class
 => ActiveSupport::StringInquirer 
ruby-1.9.3-p0 :051 > "hello " << Rails.env
 => "hello development"

简单的说,一个对象定义了 to_str 就表示它 acts_like_string,但这种实现比继承和 mix-in 要轻量很多。

#5 楼 @hooopo 我的意思是定义 to_s 即可作为 like_string 也可以,真的有需要 like_string 但 to_str 又必须和 to_s 不同的场景吗

嗯 其实我问的意思是 why 这样设计 是不是真的有必要这样

想了下,结合 LZ 所说还是有必要这样设计的。 ruby 变量没有类型 所以如果 to_s 代替 to_str,也就是所有对象皆可为字符串 甚至可能让人混淆对象的类型

#9 楼 @jjym 嗯 就是动态语言里的多态、ducking type、面向行为什么的....

匿名 #11 2012年06月24日

我习惯需要用 string 的时候先 to_s, 比如 "Hello" + Hooopo.to_s, ["Hello", Hooopo.to_s].join(" ")

to_s 必须显性调用 to_str 类似其他语言的 toString 和__str__, my_obj+str 这类场景自动转换 inspect 类似 python 的 repr

#6 楼 @jjym

其实 Ruby 中to_?to_??? 这类方法是有惯例的。

简单点说: 前者就是让你手动调用的。并且核心类有默认实现,当然,你可以重写默认实现. 后者,不是让你调用的。是系统自动调用的。鸭子类型,就是用类似方法实现的。

#9 楼 @jjym 这篇讲的也不错:http://blog.bigbinary.com/2012/06/26/to_str-in-ruby.html

If an object implements to_str method then it is telling the world that my class might not be String but for all practical purposes treat me like a string. If a class defines to_str then that class is telling the world that altought my class is not String you can treat me like a String.

#14 楼 @hooopo

Ruby could have called to_s method on e and could have produced the result. But ruby refused to do so.

Ruby refused to do so because it found that the object you are trying to add to string is not of type String. When we call to_s we get the string representation of the string. But the object might or might not be behaving like a string.

看了这篇后感觉 to_str 更像是为了避免无意义的字符串而出现的。 Ruby 在设计上很多地方都值得思考,有机会一定要看下 Matz 那本书

今天碰研究一个最佳实践,牵涉到这个这个知识点了,搜到这里,很有收获,也分享下。 ruby 是动态类型的,所以在方法内有时需要对参数类型进行检查,而这种检查最好不用 responds_to?而使用某种显示转换,而像 to_i 这样,所以我需要了解 to_i 和 to_int 的区别。

def need_num num
         puts "to_i ---"
         num.to_i.times { puts "#{num} times repeated" }

         puts "to_int ---"
         num.to_int.times { puts "#{num} times repeated" }

         puts "times ---"
         num.times { puts "#{num} times repeated" }
end

need_num 5
need_num "6"

@hooopo 谢谢分享。但是你的解释不够清晰哈,我上面这个场景,按你在 5 楼的解释,我肯定就是将num当作number来对待,那应该调用to_int,但我测试来看to_i才符合预期。你不知道用户调用num时会传进来一个 什么东西,故你不能盼着系统会的自动转换,而要自己显示转换,故应该调用to_i. @zw963 @clearJiang 总结的更到位,也更加容易理解,

呵呵,不清晰算了。。懒得解释了。

#17 楼 @hooopo 我了个去,你这个论坛就你一个人在里面说话啊。而且你可以统计一下进入了注册页,但又放弃的人的计数吗。真是讨厌现在的注册呢,为什么所有的注册登陆不能在一台机器上搞定呢。qq 的 openid 貌似不太成功,是否可以考虑做一个这样的平台呢,像我们的头像那样的。

@hooopo 我了个去,不要对偶等菜鸟失去耐心撒。很感谢,看了例子和引用材料,基本还是弄清楚了的。

我 review 时发现,to_s 要显性调用 这种说法也不精确, "puts invokes to_s method too"

#18 楼 @hhuai 就我自己在用也没动力改了。。

#16 楼 @feitian124 隐式转换是发生在多个对象之间相关操作时候的。比如两个字符串拼接、两个数组连接等。被链接的对象会发生隐式转换。你上面的例子num.to_int报错是因为字符串就没有 to_ini 方法。和隐式转换没一点关系。

good, 感谢分享,原来这就是传说中的鸭子类型。

不错。to_X to_XXX 解释比较清楚。 但是没有解释 inspect 的区别。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号