从 C 和 C++ 迁移到 Ruby
很难用项目符号列表来描述您的代码在 Ruby、C 或 C++ 中的不同之处,因为差异非常大。其中一个原因是 Ruby 运行时为您做了很多事情。Ruby 似乎与 C 的“无隐藏机制”原则背道而驰——Ruby 的重点在于让程序员的工作更轻松,而让运行时承担更多工作。除非您对代码进行性能分析以进行优化,否则在使用 Ruby 时,您不必一丁点地关心“让编译器满意”。
话虽如此,但有一点可以肯定,您的 Ruby 代码的执行速度会比“等效”的 C 或 C++ 代码慢得多。同时,您会惊叹于 Ruby 程序能够多快地启动运行,以及编写它需要多少行代码。Ruby 比 C++ 简单得多,它会把您宠坏。
Ruby 是动态类型语言,而不是静态类型语言——运行时会在运行时尽可能多地完成工作。例如,您不必提前知道您的 Ruby 程序将“链接到”(即加载和使用)哪些模块,或者它将调用哪些方法。
令人欣喜的是,Ruby 和 C 之间存在着健康的共生关系。Ruby 支持所谓的“扩展模块”。这些模块可以在您的 Ruby 程序中使用(并且从外部看,它们看起来和任何其他 Ruby 模块一样),但它们是用 C 编写的。通过这种方式,您可以将 Ruby 软件中对性能要求高的部分进行隔离,并将它们提炼成纯 C 代码。
当然,Ruby 本身是用 C 编写的。
与 C 的相似之处
与 C 一样,在 Ruby 中,...
- 如果您愿意,您可以进行过程式编程(但在幕后它仍然是面向对象的)。
- 大多数运算符相同(包括复合赋值运算符和按位运算符)。不过,Ruby 没有 `
++` 或 `--`。 - 您拥有 `
__FILE__` 和 `__LINE__`。 - 您也可以拥有常量,尽管没有特殊的 `
const` 关键字。常量性是通过命名约定强制执行的——以大写字母开头的名称是常量。 - 字符串使用双引号。
- 字符串是可变的。
- 就像 man pages 一样,您可以在终端窗口中阅读大多数文档——通过使用 `
ri` 命令。 - 您可以使用同类型的命令行调试器。
与 C++ 的相似之处
与 C++ 一样,在 Ruby 中,...
- 您拥有大部分相同的运算符(甚至包括 `
::`)。`<<` 通常用于向列表添加元素。不过有一点要注意:在 Ruby 中,您永远不会使用 `->`——它总是只是 `.`。 - `public`、`private` 和 `protected` 起着类似的作用。
- 继承语法仍然只有一个字符,但它是 `
<` 而不是 `:`。 - 您可以将代码放入“模块”中,这类似于 C++ 中的 `
namespace` 用法。 - 异常的工作方式类似,只是为了保护无辜者而更改了关键字名称。
与 C 的区别
与 C 不同,在 Ruby 中,...
- 您无需编译代码。只需直接运行它。
- 对象是强类型的(而变量名本身没有任何类型)。
- 没有宏或预处理器。没有类型转换。没有指针(也没有指针算术)。没有 typedef、sizeof 或 enums。
- 没有头文件。您只需在主源文件代码中定义函数(通常称为“方法”)和类。
- 没有 `
#define`。只需使用常量即可。 - 所有变量都存储在堆上。此外,您不必自己释放它们——垃圾收集器会处理这一切。
- 传递给方法的参数(即函数)是按值传递的,其中值始终是对象引用。
- 使用 `
require 'foo'` 而不是 `#include <foo>` 或 `#include "foo"`。 - 您不能直接访问汇编代码。
- 行末没有分号。
- 您会省略 `
if` 和 `while` 条件表达式的括号。 - 方法(即函数)调用中的括号通常是可选的。
- 您通常不使用花括号——只需使用 `
end` 关键字结束多行结构(如 `while` 循环)。 - `
do` 关键字用于所谓的“块”。没有像 C 中那样的“do 语句”。 - “块”的含义有所不同。它是一个代码块,您将其与方法调用关联起来,以便方法体在执行时可以调用该块。
- 没有变量声明。您只需在需要时即时为新名称赋值。
- 在测试真值时,只有 `
false` 和 `nil` 被评估为假值。其他所有都为真(包括 `0`、`0.0` 和 `"0"`)。 - 没有 `
char`——它们只是 1 个字符的字符串。 - 字符串不以空字节结尾。
- 数组字面量使用方括号而不是花括号。
- 当您将更多元素放入数组时,数组会自动变大。
- 如果您将两个数组相加,您会得到一个新的、更大的数组(当然,分配在堆上),而不是进行指针算术。
- 大多数情况下,一切都是表达式(也就是说,像 `
while` 语句这样的东西实际上会评估为一个右值)。
与 C++ 的区别
与 C++ 不同,在 Ruby 中,...
- 没有显式的引用。也就是说,在 Ruby 中,每个变量都只是一个自动解引用的对象名称。
- 对象是强类型但动态类型。运行时在运行时发现该方法调用是否实际起作用。
- “构造函数”称为 `
initialize` 而不是类名。 - 所有方法始终是虚拟的。
- “类”(静态)变量名始终以 `
@@` 开头(例如 `@@total_widgets`)。 - 您不直接访问成员变量——所有对公共成员变量(在 Ruby 中称为属性)的访问都通过方法进行。
- 使用 `
self` 而不是 `this`。 - 有些方法以 '?' 或 '!' 结尾。它实际上是方法名的一部分。
- 严格来说没有多重继承。尽管 Ruby 有“混入”(即您可以“继承”一个模块的所有实例方法)。
- 有一些强制性的大小写约定(例如,类名以大写字母开头,变量以小写字母开头)。
- 方法调用中的括号通常是可选的。
- 您可以随时重新打开一个类并添加更多方法。
- 不需要 C++ 模板(因为您可以将任何类型的对象分配给给定的变量,并且类型总是在运行时确定)。也没有类型转换。
- 迭代的处理方式略有不同。在 Ruby 中,您不使用单独的迭代器对象(如 `
vector<T>::const_iterator iter`)。相反,您使用容器对象的迭代器方法(如 `each`),该方法接受一个代码块,并将 successive 元素传递给它。 - 只有两种容器类型:`
Array` 和 `Hash`。 - 没有类型转换。不过,在 Ruby 中,您可能会发现它们不是必需的。
- 多线程是内置的,但截至 Ruby 1.8,它们是“绿色线程”(仅在解释器内实现),而不是原生线程。
- 单元测试库随 Ruby 一起提供。