从 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 手册一样,你可以在终端窗口中阅读大多数文档——尽管使用的是 ri 命令。
  • 你有相同的命令行调试器可用。

与 C++ 的相似之处

与 C++ 类似,在 Ruby 中,…

  • 你拥有大多数相同的运算符(甚至包括 ::)。<< 通常用于将元素追加到列表中。但请注意:在 Ruby 中你永远不会使用 ->——它总是只是 .
  • publicprivateprotected 执行类似的任务。
  • 继承语法仍然只有一个字符,但它是 < 而不是 :
  • 你可以将你的代码放入“模块”中,类似于 C++ 中 namespace 的使用方式。
  • 异常的工作方式类似,尽管关键字名称已被更改以保护无辜者。

与 C 的不同之处

与 C 不同,在 Ruby 中,…

  • 你不需要编译你的代码。你只需直接运行它。
  • 对象是强类型的(并且变量名本身没有任何类型)。
  • 没有宏或预处理器。没有类型转换。没有指针(也没有指针算术)。没有 typedefs、sizeof 或 enums。
  • 没有头文件。你只需在主源代码文件中定义你的函数(通常称为“方法”)和类。
  • 没有 #define。只需使用常量代替。
  • 所有变量都存在于堆上。此外,你不需要自己释放它们——垃圾收集器会处理这个问题。
  • 方法的参数(即函数)是按值传递的,其中这些值始终是对象引用。
  • 它是 require 'foo' 而不是 #include <foo>#include "foo"
  • 你不能下降到汇编语言。
  • 行尾没有分号。
  • 对于 ifwhile 条件表达式,你不需要括号。
  • 方法(即函数)调用的括号通常是可选的。
  • 你通常不使用花括号——只需用 end 关键字结束多行结构(如 while 循环)。
  • do 关键字用于所谓的“代码块”。没有像 C 中的“do 语句”。
  • 术语“代码块”意味着不同的东西。它用于与方法调用关联的代码块,以便方法体在执行时可以调用该代码块。
  • 没有变量声明。你只需在需要时动态地分配新名称。
  • 在测试真值时,只有 falsenil 评估为假值。其他一切都是真值(包括 00.0"0")。
  • 没有 char——它们只是一个字母的字符串。
  • 字符串不以空字节结尾。
  • 数组字面量用方括号而不是花括号括起来。
  • 当你将更多元素放入数组时,数组会自动变大。
  • 如果添加两个数组,你会得到一个新的更大的数组(当然,在堆上分配),而不是进行指针算术。
  • 通常情况下,一切都是表达式(也就是说,像 while 语句这样的东西实际上会评估为一个右值)。

与 C++ 的不同之处

与 C++ 不同,在 Ruby 中,…

  • 没有显式引用。也就是说,在 Ruby 中,每个变量都只是某些对象的自动解引用名称。
  • 对象是强类型但动态类型的。运行时在运行时发现该方法调用是否真的有效。
  • “构造函数”称为 initialize,而不是类名。
  • 所有方法始终是虚拟的。
  • “类”(静态)变量名始终以 @@ 开头(如 @@total_widgets)。
  • 你不会直接访问成员变量——对公共成员变量(在 Ruby 中称为属性)的所有访问都通过方法进行。
  • 它是 self 而不是 this
  • 一些方法以 ’?’ 或 ’!’ 结尾。它实际上是方法名称的一部分。
  • 没有严格意义上的多重继承。尽管 Ruby 有“混入”(即你可以“继承”模块的所有实例方法)。
  • 有一些强制执行的大小写约定(例如,类名以大写字母开头,变量以小写字母开头)。
  • 方法调用的括号通常是可选的。
  • 你可以随时重新打开一个类并添加更多方法。
  • 不需要 C++ 模板(因为你可以将任何类型的对象分配给给定的变量,并且类型在运行时会被解析)。也没有类型转换。
  • 迭代的完成方式略有不同。在 Ruby 中,你不使用单独的迭代器对象(如 vector<T>::const_iterator iter)。相反,你使用容器对象的迭代器方法(如 each),该方法接受一个代码块,并将连续的元素传递给该代码块。
  • 只有两种容器类型:ArrayHash
  • 没有类型转换。不过,使用 Ruby 你可能会发现它们不是必需的。
  • 多线程是内置的,但从 Ruby 1.8 开始,它们是“绿色线程”(仅在解释器中实现),而不是原生线程。
  • 单元测试库是 Ruby 的标准配置。