官术网_书友最值得收藏!

第1章 OO大智慧

1.1 對象的旅行

本節將介紹以下內容:

·面向對象的基本概念

·.NET基本概念評述

·通用類型系統

1.1.1 引言

提起面向對象,每個程序設計者[0]都有自己的理解,有的深入肌理,有的劍走偏鋒。但是無論所長,幾個基本的概念總會得到大家的重視,它們是:類、對象、繼承、封裝和多態。很對,差不多就是這些元素構成了面向對象設計開發的基本邏輯,成為數以千萬計程序設計者不懈努力去深入理解和實踐的根本。而實際上,理解面向對象一個重要的方法就是以實際的生活來類比對象世界,對象世界的邏輯和我們生活的邏輯形成對比的時候,這種體驗將會更有親切感,深入程度自然也就不同以往。

本節就從對象這一最基本元素開始,進行一次深度的對象旅行,把.NET面向對象世界中的主角來一次遍歷式曝光。把對象的世界和人類的世界進行一些深度類比,以人類的角度戲說對象,同時也以對象的邏輯反思人類。究竟這種旅程,會有什么樣的洞悉,且看本文的演義[0]。

對象和人,兩個世界,一樣情懷。

1.1.2 出生

對象就像個體的人,生而入世,死而離世。

我們的故事就從對象之生開始吧。首先,看看一個對象是如何出生的:

Person aPerson = new Person("小王", 27);

那么一個人又是如何出生呢?每個嬰兒隨著一聲啼哭來到這個世界,鼻子是鼻子、嘴巴是嘴巴,已經成為一個活生生的獨立的個體。而母親的懷胎十月是人在母體內的成長過程,母親為胎兒提供了所有的養分和舒適的環境,這個過程就是一次實實在在的生物化構造。同樣的道理,對象的出生,也是一次完整的構造過程:首先會在內存中分配一定的存儲空間;然后初始化其附加成員,就像給人取個具有標識作用的姓名一樣;最后,再調用構造函數執行初始化,這樣一個對象實體就完成了其出生的過程,例如上例中我們為aPerson對象初始化了姓名和年齡。

正如人出生之時,一身赤裸沒有任何的附加品,其余的一切將隨需而生,生不帶來就是這個意思。對象的出生也只是完成了對必要字段的初始化操作,其他數據要通過后面的操作來完成。例如對屬性賦值,通過方法獲取必要的信息等。

1.1.3 旅程

嬰兒一出世,由it成為he or she,就意味著從此融入了復雜的社會關系,經歷一次在人類倫理與社會規則的雙重標準中生活,開始了為人的旅程。同理,對象也一樣。

作為個體的人,首先是有類型之分的,農民、工人、學者、公務員等,所形成的社會規則就是農民在田間務農,工人在工廠生產,學者探討知識,公務員管理國家。[0]

對象也一樣是有類型的,例如整型、字符型等。當然,分類的標準不同,產生的類別也就不同。但是常見的分類就是值類型和引用類型兩種。其依據是對象在運行時在內存中的位置,值類型位于線程的堆棧,而引用類型位于托管堆。正如農民可以進城務工,工人也可以回鄉務農,值類型和引用類型的角色也會發生轉變,這個過程在面向對象中稱為裝箱與拆箱。這一點倒是與剛剛的例子很貼切,農民進城,工人回鄉,不都得把行李裝進箱子里折騰嘛。

作為人,我們都是有屬性的,例如你的名字、年齡、籍貫等,用來描述你的狀態信息,同時每個人也用不同的行為來操作自己的屬性,實現了與外界的交互。對象的字段、屬性就是我們自己的標簽,而方法就是操作這些標簽的行為。人的名字來自于長輩,是每個人在出生之時構造的,這和對象產生時給字段賦值一樣。但是每個人都有隨時更名的權力,這種操作名稱的行為,我們稱之為方法。在面向對象中,可以像這樣來完成:

aPerson.ChangeName("Apple Boy");

所以,對象的旅行過程,在某種程度上就是外界通過方法與對象交互,從而達到改變對象狀態信息的過程,這也和人的生存之道暗合。

人與人之間通過語言交流。人一出生,就必然和這個世界的其他人進行溝通,形成種種相互的關系,[0]融入這個完整的社會群體。在對象的世界里,你得絕對相信對象之間也是相互關聯的,不同的對象之間發生著不同的交互性操作,那么對象的交互是通過什么方式呢?對象的交互方式被記錄在一本稱為“設計模式”的魔法書中,當你不解以什么樣的方式建立對象與對象之間的關系時,學習前人的經驗,往往是最好的選擇。[0]

下面,我們簡要地分析一下對象到底旅行在什么樣的世界里?

對象的生存環境是CLR,而人的生存環境是社會。CLR提供了對象賴以生存的托管環境,制定一系列的規則,稱之為語法,例如類型、繼承、多態、垃圾回收等,在對象世界里建立了真正的法制秩序;而社會提供了人行走江湖的秩序,例如法律、規范、道德等,幫助我們制約個體,維護社會。

人類社會就是系統架構,也是分層的。上層建筑代表政治和思想,通過社會契約和法律規范為經濟基礎服務,在對象世界中,這被稱為接口。面向接口的編程就是以接口方式來抽象變化,從而形成體系。正如人類以法律手段來維系社會體系的運作和秩序一樣。

由此可見,對象的旅行就是這樣一個過程,在一定的約定與規則下,通過方法進行彼此的交互操作,從而達到改變本身狀態的目的。從最簡單的方式理解實際情況,這些體會與人的旅程如此接近,給我們的啟示更加感同身受。

1.1.4 插曲

接下來,我們以與人類世界的諸多相似之處,來進一步闡釋對象世界的幾個最熟悉的概念。

關于繼承。人的社會中,繼承一般發生在有血緣關系的族群中。最直接的例子一般是,兒子繼承父親,包括姓氏、基因、財產和一切可以遺留的東西。但并不代表可以繼承所有,因為父親隱私的那一部分屬于父親獨有,不可繼承。當然,也可能是繼承于族群的其他人,視實情而定。而在面向對象中,繼承無處不在,子類繼承父類,以訪問權限來實現不同的控制規則,稱為訪問級別,如表1-1所示。

表1-1 訪問修飾符

這些規則可以以公司的體制來舉例說明,將公司職權的層級與面向對象的訪問權限層級做類比,應該是這樣:

·public,具有最高的訪問權限,就像是公司的董事會具有最高的決策權與管理權,因此public開放性最大,不管是否同一個程序集或者不管是否繼承,都可以訪問。

·protected,類似于公司業務部門經理的職責,具有對本部門的直接管轄權,在面向對象中就體現為子類繼承這種縱向關系的訪問約定,也就是只要繼承了該類,則其對象就有訪問父類的權限,而不管這兩個具有繼承關系的類是否在同一個程序集中。

·internal,具有類比意義的就是internal類似于公司的職能部門的職責,不管是否具有上下級的隸屬關系,人力資源部都能管轄所有其他部門的員工考勤。這是一種橫向的職責關系,在面向對象中用來表示同一程序集的訪問權限,只要是隸屬于同一程序集,對象即可訪問其屬性,而不管是否存在隸屬關系。

·protected internal,可以看做是protected internal的并集,就像公司中掌管職能部門的副總經理,從橫向到縱向都有管理權。

·private,具有最低的訪問權限,就像公司的一般員工,管好自己就行了。因此,對應于面向對象的開放性最小。

另外,對象中繼承的目的是提高軟件復用,而人類中的繼承,不也是現實中的復用嗎?

而關于多態,人的世界中,我們常常在不同的環境中表現為不同的角色,并且遵守不同的規則。例如在學校我們是學生,回到家里是兒女,而在車上又是乘客,同一個人在不同的情況下,代表了不同的身份,在家里你可以撒嬌但是在學校你不可以,在學校你可以打球但在車上你不可以。所以這種身份的不同,帶來的是規則的差異。在面向對象中,我們該如何表達這種復雜的人類社會學呢?

interface IPerson
{
   string Name
   {
      get;
      set;
   }
   Int32 Age
   {
      get;
      set;
   }
  void DoWork();
}
class PersonAtHome : IPerson
{
}
class PersonAtSchool : IPerson
{
}
class PersonOnBus : IPerson
{
}

顯然,我們讓不同角色的Person繼承同一個接口:IPerson。然后將不同的實現交給不同角色的人自行負責,不同的是PersonAtHome在實現時可能是CanBeSpoil(),而PersonOnBus可能是BuyTicket()。不同的角色實現不同的規則,也就是接口協定。在使用上的規則是這個樣子:

IPerson aPerson = new PersonAtHome();
aPerson.DoWork();

另一個角色又是這個樣子:

IPerson bPerson = new PersonOnBus();
bPerson.DoWork();

由此帶來的好處是顯而易見的,我們以IPerson代表了不同角色的人,在不同的情況下實現了不同的操作,而把決定權交給系統自行處理。這就是多態的魅力,其樂無窮中,帶來的是面向對象中最為重要的特性體驗。記住,很重要的一點是,DoWork在不同的實現類中體現為同一命名,不同的只是實現的內部邏輯。

這和我們的規則多么一致呀!

當然,有必要補充的是對象中的多態主要包括以下兩種情況:

·接口實現多態,就像上例所示。

·抽象類實現多態,就是以抽象類來實現。

其細節我們將在1.4節“多態的藝術”中加以詳細討論。

由此可見,以我們自己的角度來闡釋技術問題,有時候會有意想不到的收獲,否則你將被淹沒在諸如“為什么以這種方式來實現復用”的叫喊中不能自拔。換一個角度,眼界與思路都會更加開闊。

1.1.5 消亡

對象和人,有生必然有死。在對象的世界里,它的生命是由GC控制的,而在人的世界里我們把GC稱為自然規律。進入死循環的對象,是違反規則的,必然無法逃脫被Kill的命運[0],就如同沒有長生不死的人一樣。[0]

在這一部分,我們首先觀察對象之死,以此反思和體味人類入世的哲學,兩者相比較,也會給我們更多關于自己的啟示。對象的生命周期由GC控制,其規則大概是這樣:GC管理所有的托管堆對象,當內存回收執行時,GC檢查托管堆中不再被使用的對象,并執行內存回收操作。不被應用程序使用的對象,指的是對象沒有任何引用。關于如何回收、回收的時刻,以及遍歷可回收對象的算法,是較為復雜的問題,我們將在6.3節“垃圾回收”中進行深度探討。不過,這個回收的過程,同樣使我們感慨。大自然就是那個看不見的GC,造物而又終將萬物回收,無法改變。我們所能做到的是,將生命的周期拓寬、延長、書寫得更加精彩。[0]

1.1.6 結論

程序世界其實和人類世界有很多相似的地方,本節就以這種類比的方式來詮釋這兩個世界的主角:對象和人。以演化推進的手法來描述面向對象程序世界的主角對象由生而死的全過程,好似復雜的人生。而其實,人也可以是簡單的。這是一種相互的較量,也是一種相互的借鑒。

主站蜘蛛池模板: 合山市| 通渭县| 峨眉山市| 凤庆县| 衡山县| 灵宝市| 虹口区| 花垣县| 临武县| 宁安市| 奉化市| 富民县| 泉州市| 潮安县| 泽普县| 台前县| 崇礼县| 中阳县| 荃湾区| 祁连县| 临江市| 阜宁县| 青神县| 措勤县| 玉门市| 博乐市| 政和县| 枝江市| 金溪县| 齐齐哈尔市| 喀喇沁旗| 佛坪县| 祁阳县| 报价| 阿巴嘎旗| 藁城市| 中牟县| 永年县| 庆云县| 石渠县| 荆州市|