從 C 和 C++ 到 Ruby

由於 Ruby 跟 C/C++ 的差異實在太大,很難將兩者間的差異一項一項列出。其中的一個重要理由是:Ruby 和 C 語言的「不隱藏內部機制(No hidden mechanism)」原則完全處在兩個極端上。Ruby 選擇讓人們的工作更輕鬆,但讓執行期環境(runtime)負擔加重。除非你要開始對你的 Ruby 程式碼做最佳化,你不需要關心編譯器的臉色如何。

也就是說,你可以預期 Ruby 程式將會比等價的 C/C++ 程式慢的多。然而,你也會驚訝於只需要寫這麼少的程式碼,就可以迅速地完成你的 Ruby 程式。Ruby 能完全滿足你的需求,又比C++簡單的多。

Ruby 是動態型別(Dynamically typed),而不是靜態型別(Statically typed)的程式語言。Ruby的執行期環境(runtime)會盡可能的處理所有工作。舉例來說,你不需要事先知道你的 Ruby 程式將會被連結(link)到哪一個模組,或是哪一個方法(method)將會被呼叫。

幸運的是,Ruby 與 C 有著良好的共生關係。Ruby 支援所謂的「擴充模組」。這些由 C 語言寫成的模組能夠在 Ruby 程式中使用(而且看起來與一般 Ruby 模組無異)。因此,你可以將你的 Ruby 程式中影響效能最大的部份劃分出去,用純粹的 C 語言來完成這些部分。

最後,Ruby 本身理所當然的是用 C 語言寫成。

與C語言的相似之處

與C語言相同,在Ruby中…

  • 你可以用程序式的方式寫程式(但是底層依然是物件導向的環境。)
  • 大多數的運算子都是相同的。(包含複合運算子跟位元運算子。)然而Ruby並沒有++或是--運算子。
  • 你可以使用__FILE____LINE__
  • 你可以定義常數。雖然並沒有特殊的 const 關鍵字,Ruby利用命名的慣例來強迫變數為常數:第一個字母為大寫的變數便為常數。
  • 字串由雙引號包住。
  • 字串是可變的。
  • 就像man page一樣,你可以利用ri指令在終端機視窗中閱讀大多數的文件。
  • 你也有一樣的指令列debugger可以使用。

與C++的相同之處

與C++相同,在Ruby中…

  • 大多數的運算子都是一樣的(包含::),<<常常用來將元素串接在list之後。要注意的是:Ruby中你不需要使用->,永遠只需要.
  • publicprivate,與protected的功能在兩者是類似的。
  • 物件的繼承一樣只需要一個字元,只是從 : 變成 <
  • 可以將你的程式碼放進模組(module)之中,類似 C++ 中的 namespace 的作法。
  • 例外(Exceptions)的運作方式類似。雖然為了保護無辜的人們,我們把關鍵字改了。

與C語言的不同之處

與C語言不同的是,在Ruby中…

  • 物件是強型別。(變數名稱則沒有任何的型別定義。)
  • 沒有巨集(macro)或是前處理器(preprocessor)、沒有轉型、沒有指標。
  • 沒有標頭檔(header files)、沒有typedef、沒有sizeof、也沒有enums。
  • 沒有#define。用常數來代替他們便可。
  • 在Ruby 1.8中,程式碼在執行期才被解譯,而不是被編譯成任何一種機械語言或是byte-code。
  • 所有的變數都存放在堆疊(heap)中。因此,你不需要自行釋放他們,垃圾回收機制(Garbage collector)會處理他們。
  • 方法的參數是傳參考,而非傳值。
  • require 'foo' 而不是 #include <foo> 或是 #include "foo"
  • 你不能在程式碼中插入組合語言。
  • 每行的結尾不需要分號。
  • ifwhile 這類條件運算式中,你可以省略括號。
  • 呼叫方法的括號通常是選擇性的。
  • 你不會常常使用大括號。一般只需要使用 end 關鍵字來結束一個多行的區塊(像是 while 迴圈。)
  • do關鍵字被稱作「block」,Ruby中沒有C語言的「do statement。」
  • 「block」這個詞在 Ruby 中有著不同的意義。它是指一段可以結合到一個方法呼叫的程式碼,使得該方法的本體在執行時可以呼叫該段程式碼。
  • 你不需要事先宣告變數,當你需要一個變數時直接使用一個新名字就可以了。
  • 當測試真值的時候,除了 falsenil 之外的東西都視為真(包含 00.0,以及"0"。)
  • Ruby沒有字元(char)型別,只有長度為一的字串。
  • 字串並不需要一個空位元組作為結束。
  • 陣列宣告使用中括號而非大括號。
  • 當你加入更多元素到陣列中時,陣列會自動變大。
  • 如果你將兩個陣列相加,你會得到一個更大的新的陣列,而不是指標運算的結果。
  • 大多數的情況下,一切都是一個運算式。(也就是說,while之類的東西實際上會被當做一個rvalue。)

與C++的不同

與C++不同的是,在Ruby中…

  • 你不能明確的定義參照(reference),Ruby中每個變數都會被自動解參照回原本的物件。
  • 物件型別是強型別也是動態型別。Ruby執行期環境將會在執行期的方法呼叫成功時,自行辨識型別。
  • 物件的建構子用 initialize 命名,而不是類別名稱。
  • 所有的方法都是虛擬(virtual)的。
  • 類別變數(靜態變數)的變數名稱永遠用 @@開頭。
  • 你不能直接存取成員變數,所有對公開的成員變數(在Ruby中稱作屬性, attribute)的存取都會透過方法呼叫。
  • self取代this
  • 有些方法會以 ’?’ 或是 ’!’結尾,這些符號都真的存在於方法名稱中。
  • 本質上,Ruby沒有多重繼承。然而,Ruby可以使用”mixin”。(也就是說,你可以「繼承」某個模組的所有方法)
  • 呼叫方法時的括號通常都可以省略。
  • 你可以在任何時候重新打開一個類別以加入新的方法。
  • 你不需要 C++ 的 template 機制。(因為你可以將某個變數設值為任何一種物件,型別將在執行期自動辨識。)你也不需要轉型。
  • 迭代(Iteration)的運作方式有些許不同,Ruby中你會讓你的物件mixin Enumerator模組並且直接呼叫 my_obj.each 方法,而不是使用一個獨立的迭代器(Iterator)。
  • Ruby只有兩種容器類別:ArrayHash
  • Ruby沒有型別轉換,你也會發現在Ruby中你不需要它們。
  • Ruby內建了多執行緒。但是在Ruby 1.8之中只有”green threads”(只在直譯器中有效的執行緒),而不是原生的執行緒。
  • Ruby的標準函式庫中就包含了單元測試(Unit test)函式庫。