当您初次看到 Ruby 语言代码的时候,它很可能让您想起您使用过的其他编程语言。这是当然的, 因为 Ruby 的大部分语法是 Perl、Python 和 Java(以及其他语言)的用户所熟悉的。 如果您曾经使用过这这些语言,学习 Ruby 就是小菜一碟。
本文包含了两部分。第一部分简明扼要地概述了当你从 X 到 Ruby 语言的一些所见所闻; 第二部分介绍了 Ruby 语言主要特性以及与你所熟悉的语言之间的差异。
可以期待什么: 从语言 X 到 Ruby
重要的语言特性和一些小技巧
这里介绍了学习 Ruby 语言时应该注意的 Ruby 语言的特性。
迭代器
代码块和迭代是 Ruby 语言和其他语言不太一样的地方。我们可以以索引做循环(比如 C, C++, 或者 1.5 版本以前的
Java),或者以列表做循环(比如 Perl 的 for (@a) {...}
, 还有 Python 的
for i in aList: ...
),但是在 Ruby 中,我们常会看到
关于更多 each
(还有 collect
、find
、inject
、sort
等)的信息,请参考
ri Enumerable
(和 ri Enumerable#some_method
)。
一切表达方法皆有值
表达式和语句没有区别。任何表达方法都有返回值,即使那个值是 nil,比如下面的用法:
符号不是轻量的字符串
很多 Ruby 初学者都在想办法搞清楚什么是符号和怎么使用符号。
符号最好的描述是身份证。一个符号代表了它是“谁”,而不是代表了它是“什么”。 打开 irb
来看一看他们的区别:
object_id
函数返回的是对象的身份标识。如果两个对象有相同的 object_id
, 那么他们就是相同的(指向同一个内存地址)。 可以看出,当符号在使用过一次后,任何相同字符的符号都会在内存中指向同一个对象地址。 也就是说任何相同字符的符号的 object_id
都是相同的。
(“george”)的字符串的 object_id
并不相同,这表示他们在内存种指向不同对象地址。 每当您创建一个新的字符串的时候,Ruby
会在内存中为它分配新的空间。
当您犹豫该用符号还是字符串的时候,想一下究竟字符的标识更重要(比如 Hash key)还是内容更重要 (比如前面例子里的 “george” )。
一切皆是对象
“一切皆是对象”并不是夸张。即使是类和整型变量也都是对象,您可以想使用其他对象一样使用他们:
可以改变的常量
常量并不是真正恒定的。如果您修改了一个已初始化的常量,会触发警告,但程序不会中止。 当然这也不是说您“应该”改变常量。
命名约定
Ruby 强制了一些命名约定。大写字母开头的是一个常量;美元符号($
)开头的是全局变量; @
开头的是实例变量; @@
开头的是类变量。 然而函数的名字却可以大写字母开头。这可能会导致一些混淆,比如下面的例子:
这里 Constant
是 10,而 Constant()
是 11。
关键字参数
类似 Python, 从 Ruby 2.0 开始,可以使用关键字参数定义方法
通用真值
Ruby 把任何不是 nil 和 false 的值当作真值。在 C,Python 和其他语言里,0 和一些其他的值, 比如空的列表,会被当作假值。看一看下面的 Python 代码(这个例子也可以被应用到其他语言):
这会打印出 “0 为假”,而在 Ruby 中:
会打印出 “0 为真”。
权限声明应用至作用域底部
下面的 Ruby 代码中,
您可能认为 another_method
是公有的。并不是这样的,”private” 权限声明会一直应用到类声明底部,
或者直到另外一个权限声明开始起作用。函数默认是公开的:
public
、private
和 protected
其实都是方法, 所以他们可以接受参数。如果您给他们传递一个符号的话,那么符号所代表的函数的可见性会被改变。
函数访问
在 Java 里,public
表示方法可以被任何人访问。protected
表示此类实例、继承此类的实例及在同一个包内的所有类的实例可以访问,其他人则不能。private
表示任何此类实例外的人都不能访问。
Ruby 有些不同。public
还是公开的。private
表示只有非明确指定接收者(receiver)才允许调用。私有方法调用只允许 self 为接收者。
protected
应该特别注意。受保护的方法可以被类及继承类的实例调用,同一个类的其他实例也可以调用。 来自Ruby Language FAQ 的例子:
类是开放的
Ruby 的类是开放的。任何时候你都可以打开它进行增加和修改。即使像 Integer
这样的核心类,甚至是所有对象的父类 Object
类都可以打开。Ruby on Rails 在 Fixnum
类里定义了一大堆方法来处理时间问题。请看:
有趣的方法名
Ruby 的方法名允许以问号或感叹号结尾。习惯上,以问号结尾的方法返回布尔值(如:如果接收者为空的话 Array#empty?
返回 true )。潜在“危险”方法(如修改 self 或参数的方法,exit!
等)以感叹号结尾。也不是所有修改参数的方法以感叹号结尾。 比如 Array#replace
方法将当前列表替换成另一个列表。毕竟这些方法就是为此而生的,不修改自身就没什么意义了。
单例方法(Singleton methods)
单例方法是单一对象方法。只在定义过的对象上可用。
Missing 方法
针对不存在的方法,Ruby 同样会进行处理。它会将这个不存在的方法名作为参数传递给 method_missing
。method_missing
默认会抛出一个 NameError 异常,可以根据你的应用场景重新定义这个方法,许多库都是这么做的。看下面这个例子:
上面的代码会打印出调用细节,你也可以选择任何适当的方式处理这个消息。
消息传递,非函数调用
方法调用实际将一条 消息 传递给另一个对象:
代码块也是对象,只是它们自己还不知道
代码块(实际是闭包)广泛应用于标准库。可以使用 yield
调用一个代码块,或者像下面这样,通过一个特殊的参数将它变为一个 Proc
:
调用 lambda
或 Proc.new
均可在方法外部创建代码块。
方法同样也是对象。
操作符是语法糖
Ruby 中的大部分操作符仅仅是方法调用(根据一些优先级)的语法糖。例如,你可以覆盖 Integer 的 + 方法:
你不需要 C++ 的 operator+
等。
定义了 []
和 []=
方法后,你甚至拥有了数组风格的访问方法。要想定义一元操作符 + 和 -,你也必须定义相应的 +@
和 -@
方法。下面的操作符 不是 语法糖,它们不是方法,无法重新被定义:
此外,+=
、*=
等类似操作符只是 var = var + other_var
、 var = var * other_var
等的简写。因此也无法重新被定义。
查找更多资料
当你准备学习更多 Ruby 知识的时候,请查看文档部分。