从 C/C++ 到 Ruby

很难用一个列表来描述 Ruby 与 C 或 C++ 代码的不同之处,因为差异相当大。其中一个原因是 Ruby 的运行时帮你做了很多工作。与 C 的“不隐藏内部机制”原则不同——Ruby 的关注点在于将繁重的工作交由运行时,使用者站在运行时的肩上,活的更轻松。除非或直到做代码优化,使用 Ruby 不用费心“让编译器高兴” 。

换句话说,Ruby 代码执行速度远远慢于“等价”的 C 或 C++ 代码是确定无疑的。相同的时间内,你头脑里关注的是如何快速的将一个 Ruby 程序运行起来,而且只需要很少的代码就可以做到。和把你搅成一锅粥的 C++ 相比,Ruby 要简单的多。

Ruby 是动态类型语言,而不是静态类型。它在运行的时候运行时做尽可能多的事。例如,你不用关心 Ruby 程序“链接”(也就是载入和使用)到哪里或之前调用什么方法。

可喜的是,事实证明 Ruby 和 C 之间的共生关系很和谐。Ruby 支持所谓“扩展模块”。这些模块由 C 语言编写,可以被 Ruby 程序调用(从外部来说,与其他 Ruby 模块表现和行为毫无二致)。通过这种方式,可以将性能关键部分从 Ruby 软件中切分出来,再由 C 语言打造。

当然,Ruby 本身是由 C 语言写的。

与 C 相似点

Ruby 与 C 一样的地方……

  • 如果喜欢,你可以面向过程编程(但是实际上仍然是面向对象)。
  • 大多数的操作符是一样的(包括赋值操作和位操作)。但 Ruby 没有 ++--
  • __FILE____LINE__
  • 虽然没有 const 关键字,但常量还是有的。常量由命名约定约束——以大写字母开头的是常量。
  • 字符串使用双引号。
  • 字符串是可变类型。
  • 与 man pages 类似,在终端窗口内使用 ri 命令可以浏览大部分文档。
  • 可以使用同样的命令行调试器。

与 C++ 相似点

Ruby 与 C++ 一样的地方……

  • 几乎一样的操作符(甚至 ::)。<< 常用于向列表内追加元素。值得注意的是:Ruby 使用 .,而不使用 ->
  • publicprivateprotected 功能类似。
  • 继承语法仍然只用一个字符,由 < 变成 :
  • 你可以将代码放进“模块”内,与 C++ 中使用 namespace 类似。
  • 为避免殃及池鱼,修改了异常(Exceptions)关键字, 但它们的工作类似。

与 C 相异点

Ruby 与 C 不同的地方……

  • 对象是强类型(变量名本身完全没有类型)。
  • 没有宏或预处理。没有类型转换。没有指针(也没有指针运算)。没有typedef,sizeof, enums。
  • 没有头文件。只需要在源码文件中定义你的函数(通常称作“方法”)和类即可。
  • 没有 #define 。使用常量代替。
  • 就 Ruby 1.8 而言,代码在运行时解释,而不是编译成任何机器码或二进制码。
  • 所有的变量存在于堆(heap)内。因此,不需要手动释放,垃圾回收器会帮你处理。
  • 参数通过引用传递给方法(如:函数),不是通过值传递。
  • 使用 require 'foo',而不是 #include <foo>#include "foo"
  • 不能在程序中插入组合语言。
  • 行末尾没有分号。
  • ifwhile 条件表达式不需要括号。
  • 方法调用的括号(如:函数)通常可选。
  • 通常不使用括号,使用 end 关键字结束多行结构。
  • do 关键字用于所谓的“代码块”。没有像 C 语言那样的“do statement”。
  • “代码块”意义不同。意思是当方法执行时方法体内调用的一系列代码。
  • 没有变量声明。需要时再赋予一个新的名字即可。
  • 判断真值时,只有 falsenil 当做假值。其余一切皆为真(包括 00.0""[])。
  • 没有 char 类型,有的是只包含一个字符的字符串。
  • 字符串不是以空字节结束。
  • 数组字面量使用括号而不是花括号。
  • 数组中加入更多元素时,数组会自动变大。
  • 数组相加,返回的是一个新的更大的数组(当然,分配在堆(heap)上)而不是进行指针运算。
  • 基本上,一切皆表达式(也就是说,像 while 声明也会有右值)。

与 C++ 相异点

Ruby 与 C++ 不同的地方……

  • 没有明确引用。也就是在 Ruby 中,一切变量只是对象的一个自动非关联名称。
  • 对象是强类型也是动态类型。 运行时在运行的时候才知道方法调用是否可用。
  • “构造器”是 initialize 而不是类名。
  • 一切方法都是虚的。
  • “类”(静态)变量名总是以 @@ 开头(像 @@total_widgets 这样)。
  • 你不是直接访问成员变量,所有公开的成员变量( Ruby 中称为属性)都通过方法访问。
  • 使用 self 代替 this
  • 有一些以 ?! 结尾的方法。这些符号实际是方法名的一部分。
  • 没有多重继承。然而 Ruby 有 “混入(mixins)”(比如,你可以“继承”某个模块的所有方法)。
  • 有一些强制命名约定(例如:类名以大写字母开头,变量以小写字母开头)。
  • 方法调用的括号是可选的。
  • 随时重新打开类并增加方法。
  • 不需要 C++ 模板(因为类型在运行时确定,所以可以给变量分配任意类型的对象),也没有类型转换。
  • 迭代有一点点区别。Ruby 中,不使用单独的迭代对象(像 vector<T>::const_iterator iter),当你的对象混入 Enumerator 模块,你就可以像 my_obj.each 这样调用方法。
  • 只有两种容器类型: 数组 Array 和哈希 Hash
  • 无类型转换。 你会发现在 Ruby 中,这没有必要。
  • 内置多线程,就 Ruby 1.8 而言是“绿色线程”(只在解释器中实现)而非原生线程。
  • Ruby 标准库包含了单元测试库。