1. 程式人生 > >python面向物件的程式設計思想0725

python面向物件的程式設計思想0725

類(1)

類,這個詞如果是你第一次聽到,把它作為一個單獨的名詞,總感覺怪怪的,因為在漢語體系中,很常見的是說“鳥類”、“人類”等詞語,而單獨說“類”,總感覺前面缺點修飾成分。其實,它對應的是英文單詞 class,“類”是這個 class 翻譯過來的,你就把它作為一個翻譯術語吧。

除了“類”這個術語,從現在開始,還要經常提到一個 OOP,即面向物件程式設計(或者“面向物件程式設計”)。

為了理解類和 OOP,需要對一些枯燥的名詞有了解。

術語

必須瞭解這些術語的基本含義,因為後面經常用到。下面的術語定義均來自維基百科。

問題空間

定義:

問題空間是問題解決者對一個問題所達到的全部認識狀態,它是由問題解決者利用問題所包含的資訊和已貯存的資訊主動地構成的。

一個問題一般有下面三個方面來定義:

  • 初始狀態——一開始時的不完全的資訊或令人不滿意的狀況;
  • 目標狀態——你希望獲得的資訊或狀態;
  • 操作——為了從初始狀態邁向目標狀態,你可能採取的步驟。

這三個部分加在一起定義了問題空間(problem space)。

物件

定義:

物件(object),臺灣譯作物件,是面向物件(Object Oriented)中的術語,既表示客觀世界問題空間(Namespace)中的某個具體的事物,又表示軟體系統解空間中的基本元素。

把 object 翻譯為“物件”,是比較抽象的。因此,有人認為,不如翻譯為“物件”更好。因為“物件”讓人感到一種具體的東西。

這種看法在某些語言中是非常適合的。但是,在 Python 中,則無所謂,不管怎樣,Python 中的一切都是物件,不管是字串、函式、模組還是類,都是物件。“萬物皆物件”。

都是物件有什麼優勢嗎?太有了。這說明 Python 天生就是 OOP 的。也說明,Python 中的所有東西,都能夠進行拼湊組合應用,因為物件就是可以拼湊組合應用的。

對於物件這個東西,OOP 大師 Grandy Booch 的定義,應該是權威的,相關定義的內容包括:

  • 物件:一個物件有自己的狀態、行為和唯一的標識;所有相同型別的物件所具有的結構和行為在他們共同的類中被定義。
  • 狀態(state):包括這個物件已有的屬性(通常是類裡面已經定義好的)在加上物件具有的當前屬性值(這些屬性往往是動態的)
  • 行為(behavior):是指一個物件如何影響外界及被外界影響,表現為物件自身狀態的改變和資訊的傳遞。
  • 標識(identity):是指一個物件所具有的區別於所有其它物件的屬性。(本質上指記憶體中所建立的物件的地址)

大師的話的確有水平,聽起來非常高深。不過,初學者可能理解起來就有點麻煩了。我就把大師的話化簡一下,但是化簡了之後可能在嚴謹性上就不足了,我想對於初學者來講,應該是影響不很大的。隨著學習和時間的深入,就更能理解大師的嚴謹描述了。

簡化之,物件應該具有屬性(就是上面的狀態,因為屬性更常用)、方法(就是上面的行為,方法跟常被使用)和標識。因為標識是記憶體中自動完成的,所以,平時不用怎麼管理它。主要就是屬性和方法。

任何一個物件都要包括這兩部分:屬性(是什麼)和方法(能做什麼)。

面向物件

定義:

面向物件程式設計(英語:Object-oriented programming,縮寫:OOP)是一種程式設計範型,同時也是一種程式開發的方法。物件指的是類的例項。它將物件作為程式的基本單元,將程式和資料封裝其中,以提高軟體的重用性、靈活性和擴充套件性。

面向物件程式設計可以看作一種在程式中包含各種獨立而又互相呼叫的物件的思想,這與傳統的思想剛好相反:傳統的程式設計主張將程式看作一系列函式的集合,或者直接就是一系列對電腦下達的指令。面向物件程式設計中的每一個物件都應該能夠接受資料、處理資料並將資料傳達給其它物件,因此它們都可以被看作一個小型的“機器”,即物件。

目前已經被證實的是,面向物件程式設計推廣了程式的靈活性和可維護性,並且在大型專案設計中廣為應用。 此外,支持者聲稱面向物件程式設計要比以往的做法更加便於學習,因為它能夠讓人們更簡單地設計並維護程式,使得程式更加便於分析、設計、理解。反對者在某些領域對此予以否認。

當我們提到面向物件的時候,它不僅指一種程式設計方法。它更多意義上是一種程式開發方式。在這一方面,我們必須瞭解更多關於面向物件系統分析和麵向物件設計(Object Oriented Design,簡稱 OOD)方面的知識。

下面再引用一段來自維基百科中關於 OOP 的歷史。

面向物件程式設計的雛形,早在 1960 年的 Simula 語言中即可發現,當時的程式設計領域正面臨著一種危機:在軟硬體環境逐漸複雜的情況下,軟體如何得到良好的維護?面向物件程式設計在某種程度上通過強調可重複性解決了這一問題。20 世紀 70 年代的 Smalltalk 語言在面向物件方面堪稱經典——以至於 30 年後的今天依然將這一語言視為面嚮物件語言的基礎。

電腦科學中物件和例項概念的最早萌芽可以追溯到麻省理工學院的 PDP-1 系統。這一系統大概是最早的基於容量架構(capability based architecture)的實際系統。另外 1963 年 Ivan Sutherland 的 Sketchpad 應用中也蘊含了同樣的思想。物件作為程式設計實體最早是於 1960 年代由 Simula 67 語言引入思維。Simula 這一語言是奧利-約翰·達爾和克利斯登·奈加特在挪威奧斯陸計算機中心為模擬環境而設計的。(據說,他們是為了模擬船隻而設計的這種語言,並且對不同船隻間屬性的相互影響感興趣。他們將不同的船隻歸納為不同的類,而每一個物件,基於它的類,可以定義它自己的屬性和行為。)這種辦法是分析式程式的最早概念體現。在分析式程式中,我們將真實世界的物件對映到抽象的物件,這叫做“模擬”。Simula 不僅引入了“類”的概念,還應用了例項這一思想——這可能是這些概念的最早應用。

20 世紀 70 年代施樂 PARC 研究所發明的 Smalltalk 語言將面向物件程式設計的概念定義為,在基礎運算中,對物件和訊息的廣泛應用。Smalltalk 的建立者深受 Simula 67 的主要思想影響,但 Smalltalk 中的物件是完全動態的——它們可以被建立、修改並銷燬,這與 Simula 中的靜態物件有所區別。此外,Smalltalk 還引入了繼承性的思想,它因此一舉超越了不可建立例項的程式設計模型和不具備繼承性的 Simula。此外,Simula 67 的思想亦被應用在許多不同的語言,如 Lisp、Pascal。

面向物件程式設計在 80 年代成為了一種主導思想,這主要應歸功於 C++——C 語言的擴充版。在圖形使用者介面(GUI)日漸崛起的情況下,面向物件程式設計很好地適應了潮流。GUI 和麵向物件程式設計的緊密關聯在 Mac OS X 中可見一斑。Mac OS X 是由 Objective-C 語言寫成的,這一語言是一個仿 Smalltalk 的 C 語言擴充版。面向物件程式設計的思想也使事件處理式的程式設計更加廣泛被應用(雖然這一概念並非僅存在於面向物件程式設計)。一種說法是,GUI 的引入極大地推動了面向物件程式設計的發展。

蘇黎世聯邦理工學院的尼克勞斯·維爾特和他的同事們對抽象資料和模組化程式設計進行了研究。Modula-2 將這些都包括了進去,而 Oberon 則包括了一種特殊的面向物件方法——不同於 Smalltalk 與 C++。

面向物件的特性也被加入了當時較為流行的語言:Ada、BASIC、Lisp、Fortran、Pascal 以及種種。由於這些語言最初並沒有面向物件的設計,故而這種糅合常常會導致相容性和維護性的問題。與之相反的是,“純正的”面嚮物件語言卻缺乏一些程式設計師們賴以生存的特性。在這一大環境下,開發新的語言成為了當務之急。作為先行者,Eiffel 成功地解決了這些問題,併成為了當時較受歡迎的語言。

在過去的幾年中,Java 語言成為了廣為應用的語言,除了它與 C 和 C++ 語法上的近似性。Java 的可移植性是它的成功中不可磨滅的一步,因為這一特性,已吸引了龐大的程式設計師群的投入。

在最近的計算機語言發展中,一些既支援面向物件程式設計,又支援面向過程程式設計的語言悄然浮出水面。它們中的佼佼者有 Python、Ruby 等等。

正如面向過程程式設計使得結構化程式設計的技術得以提升,現代的面向物件程式設計方法使得對設計模式的用途、契約式設計和建模語言(如 UML)技術也得到了一定提升。

列位看官,當您閱讀到這句話的時候,我就姑且認為您已經對面向物件有了一個模糊的認識了。那麼,類和 OOP 有什麼關係呢?

定義:

在面向物件程式設計,類(class)是一種面向物件計算機程式語言的構造,是建立物件的藍圖,描述了所建立的物件共同的屬性和方法。

類的更嚴格的定義是由某種特定的元資料所組成的內聚的包。它描述了一些物件的行為規則,而這些物件就被稱為該類的例項。類有介面和結構。介面描述瞭如何通過方法與類及其例項互操作,而結構描述了一個例項中資料如何劃分為多個屬性。類是與某個層的物件的最具體的型別。類還可以有執行時表示形式(元物件),它為操作與類相關的元資料提供了執行時支援。

支援類的程式語言在支援與類相關的各種特性方面都多多少少有一些微妙的差異。大多數都支援不同形式的類繼承。許多語言還支援提供封裝性的特性,比如訪問修飾符。類的出現,為面向物件程式設計的三個最重要的特性(封裝性,繼承性,多型性),提供了實現的手段。

看到這裡,看官或許有一個認識,要 OOP 程式設計,就得用到類。可以這麼說,雖然不是很嚴格。但是,反過來就不能說了。不是說用了類就一定是 OOP。

編寫類

首先要明確,類是對某一群具有同樣屬性和方法的物件的抽象。比如這個世界上有很多長翅膀並且會飛的生物,於是聰明的人們就將它們統一稱為“鳥”——這就是一個類,雖然它也可以稱作“鳥類”。

還是以美女為例子,因為這個例子不僅能閱讀本課程不犯困,還能興趣昂然。

要定義類,就要抽象,找出共同的方面。

class 美女:        #用 class 來宣告,後面定義的是一個類
    pass

好,現在就從這裡開始,編寫一個類,不過這次我們暫時不用 Python,而是用虛擬碼,當然,這個程式碼跟 Python 相去甚遠。如下:

class 美女:
    胸圍 = 90
    腰圍 = 58
    臀圍 = 83
    面板 = white
    唱歌()
    做飯()

定義了一個名稱為“美女”的類,其中我約定,沒有括號的是屬性,帶有括號的是方法。這個類僅僅是對美女的通常抽象,並不是某個具體美女.

對於一個具體的美女,比如前面提到的蒼老師或者王美女,她們都是上面所定義的“美女”那個類的具體化,這在程式設計中稱為“美女類”的例項。

王美女 = 美女()

我用這樣一種表達方式,就是將“美女類”例項化了,對“王美女”這個例項,就可以具體化一些屬性,比如胸圍;還可以具體實施一些方法,比如做飯。通常可以用這樣一種方式表示:

a = 王美女.胸圍

用點號.的方式,表示王美女胸圍的屬性,得到的變數 a 就是 90.另外,還可以通過這種方式給屬性賦值,比如

王美女.面板 = black

這樣,這個例項(王美女)的面板就是黑色的了。

通過例項,也可以訪問某個方法,比如:

王美女.做飯()

這就是在執行一個方法,讓王美女這個例項做飯。現在也比較好理解了,只有一個具體的例項才能做飯。