天天看點

《UML面向對象設計基礎》—第1章1.5節消息

本節書摘來自異步社群《uml面向對象設計基礎》一書中的第1章1.5節消息,作者【美】meliir page-jones,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

1.5 消息

uml面向對象設計基礎

對象通過消息請求另一個對象執行活動。許多消息還具有将資訊從一個對象傳送給另一個對象的作用。大多數老前輩都将消息列為重要的面向對象特性。

消息(message)是發送對象obj1向目标對象obj2發送請求的載體,申請對象obj2的一個方法。

本節對消息特性進行了剖析,描述了消息參數的特點,發送消息對象的角色,接收消息對象的角色及消息的三種類型。

1.5.1 消息結構

消息由幾個含義組成,每個含義在面向對象設計中都十分重要。實際上,本書從頭到尾會多次用到消息的特性。

對象obj1為給對象obj2發送一個顯式消息,對象obj1必須知道三件事情:

① obj2的句柄。顯然,你發送一個消息時,應該知道給誰發送。obj1通常将obj2的句柄儲存在它的一個變量中。

② obj1希望執行的obj2操作名稱。

③ obj2執行其操作時所要求的所有附加資訊(參數)。

發送消息的對象(obj1)稱為發送者,接收消息的對象(obj2)稱為目标對象,也可以分别稱為客戶機(client)和伺服器(server)。

機器人軟體提供了幾個消息的例子,其中一個為:

hom1.turnright;

其中,hom1表示該消息(含有句柄)的目标對象。回想一下,指派語句。

var hom1 :=hominoid.new給hom1賦的句柄)。turnright是目标對象執行操作的名稱。這個消息不需要任何參數:turnright總是旋轉90°。

發送消息和調用傳統的函數或過程有些類似。如用“準o.o.”語言,可以寫出下面的語句:

請注意這種倒置:使用傳統的軟體技術,我們先申請一個過程單元,然後向其提供操作的對象;在面向對象中,我們先申請一個對象,然後執行其中一個過程單元。

到此為止,這種差別似乎隻停留在文法上,至多是觀念上的。然而,當我在1.8節讨論多态性、重載及動态關聯時,将體會到“先對象後過程”所引起的面向對象結構和傳統結構之間的重要差别。因為不同的對象類可以使用相同的操作名稱執行不同特定類的行為,或執行含義不同的類似行為。

1.5.2 消息參數

與傳統的子程式一樣,大多數消息都可以傳入或傳出參數。例如,如果名為 advance的操作傳回一個标志,儲存行進的輸出,于是有下面的形式:

是以,給予目标對象的消息結構由激活目标操作的原形(signature)所定義。這個原形包括三個部分:操作名稱,輸入參數清單(字首為 in),輸出參數清單,也稱傳回參數(字首為out)。每個參數清單都可以為空,在兩個清單中可能出現相同的參數或隻在字首為inout的清單中出現一次,但在純面向對象中很少出現這種情形。為簡短起見,通常省略關鍵字in,将其作為預設字首。

《UML面向對象設計基礎》—第1章1.5節消息

消息的參數反映了面向對象軟體和傳統軟體之間的另一個基本差別。在純面向對象環境中(如smalltalk),消息參數不是資料,而是對象句柄,是以,消息參數也當作對象。

例如,圖1.10a以非正式的圖形表示法說明了機器人程式中的一個消息:

hom1.advance(noofsquares,out advanceok)。

《UML面向對象設計基礎》—第1章1.5節消息

如果在執行消息時暫停hominoid程式的執行,取出消息參數的值,我們将發現意想不到的結果。如:

noofsquare被置為123432

advanceok 被置為664730

為什麼會得到這些奇怪的數字?因為123432可能為對象(integer類)的句柄,通常為整數2,664730可能為對象(boolean類)的句柄,通常為邏輯值true,在面向對象環境中最好不用這些精确的數字,我使用這些數字隻是用于說明。

如果你更喜歡圖1.10b用uml表示方法來表示這個消息,第3章至第7章将會更深入地讨論這方面内容。

《UML面向對象設計基礎》—第1章1.5節消息

另外,再舉一個例子,如果我們正執行一個面向對象的個人系統并做相同的事情,可能發現參數empofmonth被置為441523。441523可能是對象(employee類)的句柄表示jim spriggs先生。

1.5.3 消息中的對象角色

本節讨論面向對象系統中對象的四個角色。一個對象可以是:

消息的發送者。

消息的目标。

表示另一個對象中的變量(見1.4節)。

表示消息中傳入和傳出的參數(見1.5.2節)。

一個給定的對象在生存期可以扮演一個或多個角色。在圖1.11中,我們可以看到所有這些角色。

《UML面向對象設計基礎》—第1章1.5節消息

從這個圖1.11中,我們來看一下對象obj的一個操作op。這個操作發送消息給obj的三個變量指向的每一個對象。第一個消息隻有一個輸入參數;第二個消息隻有一個輸出參數;第三個消息既有輸入參數也有輸出參數。每個參數本身指向一個對象。這個結構非常典型地說明了對象操作如何與對象變量進行互動。

一些作者建議每個對象要麼是“發送者”要麼是“目标”。但實際不然,如圖1.12所示。

《UML面向對象設計基礎》—第1章1.5節消息

對于message1,obj1是發送者,obj2是目标。對于message2,obj2是發送者,obj3是目标。是以我們看到,不同的時刻,同一個對象既可以是發送者又可以是目标。術語“發送者”和“目标”是相對給定消息而言的。它們不是對象本身固有的特性。

在純面向對象環境中隻有對象,每個對象扮演一個或前面提到的四個角色中的幾個角色。在純面向對象中不需要資料,因為對象可以完成資料完成的所有軟體功能。在smalltalk(非常純的面向對象語言)中,确實沒有任何資料!運作時隻有指向其他對象的對象(通過變量),通過傳遞對象的句柄進行對象之間的通信。

但在c++(一種既面向資料或函數又面向對象的混合語言)中,參數可以表示任何資訊。如果你的c++程式與smalltalk一樣純,那麼所有的參數都表示對象。但如果你将資料和對象混合在c++程式中,那麼有一些參數就是簡單的資料(或資料的指針)。對于java語言也是如此,盡管java語言遠遠不如c++那樣随意。

1.5.4 消息的類型

對象可以接收三種類型的消息:報告消息,詢問消息及祈使消息。本節對每一種消息進行舉例說明。再一次借用機器人程式。在本書的最後第12章,讨論通信對象不同的設計方法時,再回到這些消息類型。

報告消息(informative message)是指向對象提供自我更新資訊的消息(也稱更新、向前或推出消息)。這是一種“面向過去”的消息,通常通知對象已經發生的事情。

報告消息的一個例子是employee.got(marriagedate:date)。這個消息告訴一個雇員對象某個雇員已經在某個日期結婚。通常,報告消息告訴一個對象由該對象表示的在現實世界中已經發生的事情。

詢問消息(interrogative message)是請求一個對象顯示自身一些資訊的消息(也稱為讀、向後或回拉消息)。這是一種“面向現在”的消息,向對象詢問目前資訊。

詢問消息的一個例子是hom1.location,向機器人詢問目前所在的方格位置。這類消息實際上不改變任何事情,通常是向目标對象詢問其表示的資訊。

祈使消息(imperative message)請求對象對本身、另一個對象或系統環境執行某些操作(也稱強制或動作消息)。這是一種“面向未來”的消息,請求對象執行将來的某些操作。

祈使消息的一個例子是hom1.advance,使機器人向前移動。這種消息通常使目标對象執行一些重要的算法。

類似地,假設向機器人發送下面的祈使消息:

hom1.gotolocation(square:square,out feasible:boolean)

該消息請求機器人隻要可行,就走到特定的方格(機器人執行的計算量非常大)。

在實時的面向對象系統中,對象需要控制一些硬體,通常包含許多祈使消息。這些系統清楚地說明将要執行的祈使消息。下面是取自機器人世界的一個例子:

robotlefthand.gotolocation(x,y,z:length,theta1,theta2,theta3:angle)

這個消息将使機器人的左手擡到某個位置并在空間定位。該算法可能要求機器人的手、機器人的胳臂或機器人本身移動。六個參數表示了手的六個自由度,以三維空間表示。

下面讓我們從消息轉到面向對象公認的基本屬性即對象類。

本文僅用于學習和交流目的,不代表異步社群觀點。非商業轉載請注明作譯者、出處,并保留本文的原始連結。

繼續閱讀