物件導向是一個挺讓人迷惑的措辭.叫一切東西都是物件導向會讓別人覺得你很時髦. Ruby 聲稱自己是物件導向的指令碼語言;但究竟什麼才是"物件導向"? 我們已經有了各種各樣的答案,但所有這些恐怕都歸結於同一件事.與其快速地概括它,不如讓我們先花點兒時間考慮一下傳統的編程模式. 傳統意義上,一個編程問題從出現的各種資料,以及處理資料的過程(procedures)著手.在這一模式下,資料是呆板,被動和無用的;它完全的求助於那個體積龐大的,主動的,邏輯性的,全能的過程體. 這一做法的問題在於程式是由程式員寫的,而他們僅僅能在工作中記下為數不多的細節.而隨著工程的加大,它的核心也增長到難以記住整個工程是如何工作.細微的失誤和敲打錯誤變得越來越容易造成難以發現的臭蟲(bugs).繁雜和意外的幹擾開始在核心內出現,維護也變得像企圖抓住一隻憤怒的烏賊還要不讓它的觸鬚碰到你臉.當然,對於傳統方法,我們也有很多指導你去縮小和檢測這些臭蟲的方法,但更好的解決方案是徹底的改變我們的工作方式. 而物件導向所做的就是讓我們將現實的,重複性的邏輯工作交給資料本身;它將我們對資料的概念從被動變為主動.換種說法:
- 我們不再讓資料像一個開口的盒子一樣讓我們隨意地伸手進去並取出東西.
- 我們將其看作一個封口的並帶有開關和刻度盤的機器.
上面所說的"機器"的內部可能相當簡單或者複雜;我們不能從外面窺視,我們也不能允許自己開啟機器外殼(除非我們確實發現其中有誤),因此我們只需要通過撥動開關,讀取刻度來操作資料.機器一旦建好,我們便不再必須考慮它是如何運轉. 也許,你會覺得這是在無端的增加自己的工作量,但這一方法可以讓我們有效避免事情向壞的方向發展. 讓我們從一個簡單的毫無實際價值卻至少能說明部分概念的例子開始.你的汽車有個計程器.它的工作就是記錄從上次複位以來的行車路 程.我們將如何用程式設計語言建模?在C裡面,這個計程器也許就是個數值變數,大概是float類型的.這個程式會通過每隔一定的行程增加它的值,在合適的時候也會複位為零.哪裡會出問題呢?程式裡的一個臭蟲會無端的向這個變數賦一個偽值,這可以由某些未預料到的原因而發生.任何有過C編程經驗的人都會知道那會花掉數小時或數天來除掉這個當找出時簡單得荒唐無比的臭蟲.(找出它的那一刻往往會使勁地拍拍前額) 同樣的問題在使用物件導向時會從一個截然不同的角度著手.當設計它時,程式員會問的頭一件事不會是"什麼是最類似它的資料類型?"而是"究竟這玩意兒是幹什麼的?"這不同之處引出了一個稍帶難度的東西.我們需要花點兒時間確定到底計程器是用來幹什麼的,外部世界希望怎樣操縱它.然後我們決定構造一個允許我們增加,複位,讀值的小機器,再就沒別的了. 我們並未提供一種用於向計程器賦任意值的方法:為什麼?因為我們都知道計程器不是那樣工作的.你只能向計程器做那定義好的幾件事,而且是那些允許我們去做的事.因此,如果程式裡的別的什麼東西錯誤地向其賦值(比如,車的溫度控制器),這立刻意味著錯誤的發生.當運行它的時候(或者當編譯時間,視語言的性質而定)我們便會被告之禁止向計程器這個對象賦任意值.給出的訊息也許並非如此清楚,但它應該接近其真實原因.這並不防止錯誤的發生,是吧?但它很快給我們直接指出了問題所在.這隻是OO編程會為我們節約很多時間的許多方法中的一個. 一般的,我們會考慮將上面的那玩意兒抽象化,因為建個工廠來造機器比一個個單獨地造要簡單的多.我們不希望直接的造單獨的計程器; 換句話,我們希望所有的計程器都能由一個模型造出.這個模式(如果你喜歡,叫它計程器工廠)對應於我們所稱的一個類,每一個由它產生的單獨的計程器(或由工廠造出)對應於一個對象.許多物件導向的語言要求我們在擁有一個新的對象之前定義它的類,但Ruby不是如此. 當然運用面對對象語言並不意味著就會有好的面對對象設計.實際上,用任何語言都有寫出模糊,粗心,多蟲,低造詣及不穩定的代碼.Ruby能為你做的(作為反例,特別是C++)是讓OO編程的實踐足夠自然,即使你僅僅在小範圍內使用也不會感到必須憑藉醜陋的代碼去提高效率.我們將會隨著這本手冊深入地討論Ruby實現這些預定目標的機制;下一章將是"開關和刻度表"(對象方法),然後我們將討論到"工廠"(類).你還會跟我們來嗎? |