一些程式語言(如C++和CLOS)提供了多重繼承機制:一個類可以繼承自多個超類。例如,一個House可能繼承自一個Building類(連同Office和Hospital類一起)和Residence類(連同Apartment類一起)。儘管多重繼承可能成為一種語言強有力的特徵,但是由於它會增加該語言的複雜性和歧義,因此許多物件導向語言都沒有加入它。
Ruby支援單繼承。然而,它還提供了mixin-它提供了多繼承的許多特徵。一個mixin是一種"模組"類型。為此,你必須首先理解在Ruby中模組的含義。
在Ruby中,模組是一種把方法和常數分組的方式。它與類相似,但是一個模組沒有執行個體並且也沒有子類。也許解釋模組的最好方法是舉一個例子。假定你正在開發一個製造業應用程式。該程式需要存取大量的科學公式和常數,那麼你可以或者是建立一個通用類來把這些放在其中或者是建立一個模組。模組的優點在於,在存取其中的公式時,根本沒有任何執行個體擾亂所帶來的煩惱。
module Formulas ACCELERATION = 9.8 LIGHTSPEED = 299792458 def energy (mass) mass*(LIGHTSPEED**2) end def force (mass) mass*ACCELERATION end end |
現在,這些公式方法和常數可以被任何數目的其它類或其自身所使用:
irb(main):046:0> Formulas.force(10) => 98.0 irb(main):047:0≫ Formulas::ACCELERATION =≫ 9.8 |
注意,為了調用一個模組方法或使用一個模組常數,你必須使用類似於調用一個類方法的標誌。為了調用一個模組方法,你需要使用模組類名,後面跟著一個點,再跟著模組方法名。為了引用模組常數,你可以使用模組名,後面跟著兩個冒號,再跟著常數名。
除了作為方法和常數的"公用"應用以外,模組還可以協助定義多重繼承。一個mixin是一個簡單的"包括"有一個類定義的模組。當一個類包括一個模組時,所有的模組中的方法和常數都成為類的執行個體方法和常數。例如,假定上面定義的Formula模組作為一個mixin被添加到Rectangle類。為此,你要使用"include"關鍵字:
class Rectangle include Formulas end |
現在,Rectangle的執行個體具有了它們可以使用的force和energy方法,並且Rectangle類能夠訪問常數ACCELERATION和LIGHTSPEED:
irb(main):044:0> class Rectangle irb(main):045:1> include Formulas irb(main):046:1> end => Rectangle irb(main):047:0> Rectangle.new(4,5).force(10) => 98.0 irb(main):048:0> Rectangle::LIGHTSPEED => 299792458 |
這意味著,mixin給Ruby中的類帶來了許多多重繼承的優點,卻避開了多重繼承中存在的問題。
十一、 控制流程
象所有的程式語言一樣,Ruby提供了一組控制流程命令,這包括條件陳述式(if/else結構),case語句和迴圈語句(do,while和for),還提供了象Ada和Java等語言中的異常處理能力。下面是Ruby中的一些控制流程語句的樣本:
ifarea > 100 "big" else "small" end case height | when 1 | print "stubby/n" | when 2..10 #高度範圍為2~10 | print "short/n" | when 10..20 #高度範圍為2~10 | print "tall/n" | end aRect = Rectangle.new(4,6) while aRect.area < 100 and aRect.height < 10 aRect.doubleSize() end for element in [2, 9.8, "some string", Math::PI] #遍曆對象集合 print "The type is: " + element.type.to_s + "/n&" end |
控制語句通常非常直接,但是如前面的case語句和for迴圈語句所顯示的,Ruby借鑒了其它一些語言特徵和普通的物件導向的特性。
異常處理類似於Java中的"try...catch...finally"語句。在Ruby中,它們更改為"begin...rescue...ensure"語句:
begin #實現一些事情 rescue ##處理錯誤 ensure #做一些清理工作,如關閉一個開啟的檔案等 end |
為了在你的代碼中引發一個異常,你只需要簡單地調用raise方法:
if area < 0 raise else if area > 0 and area < 10 raise "Rectangle too small" else if area > 100 raise TooBigException "Rectangle too big" end |
第一個raise調用建立一個RuntimeError。第二個raise建立一個顯示一條訊息的RuntimeError。最後一個raise調用一個TooBigException的新執行個體(由它建立一個粗略定義的錯誤),並設定它的適當訊息。
一個Ruby小程式
為了協助你更好地掌握Ruby的基礎知識,我在本文中提供了一個小程式供你學習之用。為了使這個程式工作,你可以下載並把該檔案解壓到你的檔案系統。之後,它將建立一個examples檔案夾,在這個目錄下共有9個Ruby代碼檔案(.rb檔案)。本文中的代碼就包含在這些檔案中。另外,你會找到一個testShapes.rb檔案,它是測試Ruby的Rectangle,Square和Circle對象的主檔案。只需簡單地開啟一個命令提示字元並運行testShapes.rb檔案即可。
你將注意到,在testShapes.rb和另外一些代碼中,檔案以"require"再加上一個檔案名稱開頭(象rectangle.rb)。這是在你的Ruby程式中加入或使用來自於其它檔案代碼的Ruby標誌。
總結
Ruby能否接管Java或C#而成為業界領先的現代軟體開發語言?儘管Ruby可能變得十分流行,但我對此仍抱有懷疑態度。作為一名在業界摸爬滾打多年的專業人員,我對其偶然性並不感到驚訝,但我還是比較注重實效的。例如,我發現Smalltalk是一種比Java優越的進階語言,然而優越並不會總會贏。現代語言背後總存在大量的技術和市場方面的支援。庫,開發套件,架構,架構,連接器,適配器,支援平台,服務,知識庫,能乾的Team Dev,等等,都會被配置到位以支援象Java這樣的程式語言。並且,無論你喜歡與否,Sun和Microsoft主宰下的市場在未來一段時間內肯定還是開發環境的勝者。
那麼,為什麼還要探討Ruby呢?作為一種Perl或Python指令碼語言的代替(這正是它的最初目的)或快速原型開發工具,Ruby可能特別有用。一些人也已經看到了Ruby的威力,並且開始把Ruby作為一種偉大的方法進行編程教學。根據我的本地Ruby使用者組的成員提供的資訊,有一些人正在把它應用於測試生產系統。不僅如此,我將邀請你,就象Bruce Tate和Dave Thomas邀請我一樣來探討一下這種語言的力量和美麗之處。即使Ruby不會得到廣泛使用,但是隨著人們對它的逐漸認識和試用,它一定會找到適應自己的編程環境。