从 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 一起提供。