@elibinary
2016-11-12T13:00:47.000000Z
字数 1381
阅读 685
Ruby
Ruby 是有很多语言发展而来的,它在借鉴了这些语言的很多特性的同时,也有很多自己处理问题的方式,有时候这些方式会令你困惑或惊讶。
首先先来看一下 ruby 中的 True 和 False。在处理真值假值上面,很多语言都有着不同的处理方式。在我以前用过的语言中,就有很多 0 表示假的例子,比如 c 语言中的定义: 0 为 false,!0 (即所有非 0 值)为 true 。
那么在 ruby 中是怎样呢,实际上在 ruby 中区别真假值的规则非常简单,有别于其它很多语言,ruby 中的定义是这样的: 除了 false 和 nil ,其余的所有值都是真!没错,0 值也是真,这一点曾令我栽过不止一次跟头。
并且在 ruby 中,true 和 false 不同于很多其它语言,它们不是关键字,当你查看它们的 class 时,会发现
true.class
# => TrueClass
false.class
# => FalseClass
可以看出,true 和 false 和普通的对象一样,可以调用在它之上的任意方法,同时 ruby 也定义了 TRUE 和 FALSE 常量,而它们仅仅是对这些 true 和 false 对象的引用。其实在上边就已经说过了,在 ruby 中除了 false 和 nil 之外的任何对象都可以表示真值,因此定义的 true 对象来专门表示真值是冗余的,true 对象的存在其实只是单纯的为了方便而已。
但是这个时候又会引出另一个困惑,那就是有时我们需要去区别 false 和 nil,这个时候通常会选用两种方式来判断: nil? 或 ‘==’.
并且在使用 ‘==’ 方法的时候,书中建议把 false 作为左操作对象。这并不是有些语言中一些建议规范或 style 一样的建议,而是这样做是有其用意的。当你把 false 作为左值的时候其实就相当于调用 FalseClass#== 这个方法,这样可以很放心的确定如果右边的操作对象也是 false 对象时,返回 true。而如果把待比较对象置于左位置,那么就相当于调用该待比较对象的 ‘==’ 方法,当然其也是继承自 Object 方法,但是如果它复写了 Object#== 方法的话,就有可能导致出现预期以外的结果,这是我们不想看到的。
而对于 nil 来说,还有另外一些问题。在 Ruby 的类型系统的运作方式下,任何对象都可以是 nil,因为 Ruby 程序中的每一个对象都源自 BasicObject 这个类,那么也就是说在程序运行过程中一个类的对象是能够被另一个类的对象轻易替换的。在Ruby程序中,相比于当前对象是什么(is_a?),它更在意当前对象能够响应什么方法(respond_to?)。当该对象无法响应其方法时,就抛出 error。
在程序中,很多时候一些错误都产生自
undefined method xxx for nil::NilClass
真是令人讨厌呀,这就导致当你在定义方法时最好都假设任何对象都可以为nil并做好处理工作,比如做 nil? 等这类判断。
或者很多时候还使用 Object 定义的几种基础转换方法: to_s, to_i 等。因为令人愉悦的,NilClass 也是可以正常响应这类方法的,比如 nil.to_s 就会返回一个空字符串。另外还有一点要指出, 比如 String#to_s 方法只是简单的返回 self 而不会去做任何的转换和复制,这样的就有一大好处,当 to_s 的调用方本身就是一个 string 时,那么此方法的开销相当的小。