本節書摘來自異步社群《uml面向對象設計基礎》一書中的第1章1.12節答案,作者【美】meliir page-jones,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
1.12 答案
uml面向對象設計基礎
①(a) 有兩個建議:一是假設start方塊完全被牆包圍,二是假設某人在方格中忘記标記finish方塊。修改算法處理這兩種情況以及其他任何你考慮到的異常情況,如沒有對advanceok是否為真安全檢查。
(b)該操作中的問題是:grid對象中的inserthominoid操作需要location:square (hominoid對象的開始位置)的資訊嗎? 應該使用該資訊告訴homoid對象它的初始位置,但homoid沒有定義setlocation操作!是以,不應在grid中定義inserthominoid操作,而應在homoid中定義insertintogrid(grid:grid,location:square,out insetok:boolean)操作。此外,還需要在grid中定義isawalllocation:boolean操作。
② 回答是肯定的。對象有一個不必聲明的變量(實際上是常量),儲存自己的句柄。該變量由關鍵字self,this,this 或current(分别對應smalltalk,c++,java或eiffel)來命名。
③ 因為這樣做會使消息的目标改變了其中一個參數的句柄,這是一種拙劣的設計方法。消息的發送者有權保證其變量的句柄在發送消息的前後保持一緻。少數語言禁止這種方法;在其手冊中有這樣的說明:“參數通過傳送值進行對象通路,且不能被目标操作代碼改變。”
④ 在徹底的面向對象語言如smalltalk中,所有一切的都是對象;實際上,smalltalk堅決地進行“不含資料”的定位。例如,在smalltalk中下面的加法表達式
x <- 5 + 7
解釋為“向參數對象5和對象7發送消息plus。”指派操作符(<-)解釋為“用變量x替換對象12的句柄。”然而并不是所有面向對象語言都像smalltalk那樣嚴格。在類似eiffel的語言中,仍然有資料類型(如integer,real,char,boolean等)。但任何主要的結構在運作時是建立對象執行個體而不是資料執行個體的類。由于程式設計原因,eiffel妥協了“所有都是對象”的原則:将整數、字元等作為可以與c代碼接口相容的資料類型。在c++中,具有标準資料類型的标準c程式可以與c++程式混合使用。是以,在c++中所有顧慮可以打消!但當我告訴人們純面向對象中沒有資料時,經常受到人們的抨擊。最普通的例子是人們用integer和date反對我。為什麼這些是類而不是傳統的資料類型?在使用數字5之前,是否必須先聲明integer.new,而在使用1066年9月25日之前,是否必須先聲明date.new ?回答是否定的。諸如integer或date這樣的類被稱為文字類(literal classes)。屬于文字類的對象稱為文字對象(literal objects)。文字對象就是其表示的值。大多數文字對象是不變的:從不改變值。盡管每種面向對象語言都有其處理文字類的方式,但多數語言假設文字類的所有執行個體是預先定義的(或在原處通過轉換類似“3月15日”的文本串建立的)。在将這種“類”作為标準資料類型的語言中,執行個體實際上是傳統的資料值而不是對象。在下面兩種情況下,從文字類進行執行個體化是不必要的也是非法的:
<code>`</code>javascript
integer.new; // 非法代碼!
date.new; // 在大多數語言中是非法代碼!
public boolean navigate( )
hominoid hom = new hominoid ( );// 建立hominoid的新執行個體,由hom表示
int onesquare = 1; // 常量
int initialturncount;
square startsquare = this.start;
boolean insertok = this.inserthominoid(hom,startsquare);
//如果成功inserthominoid傳回true
if (!insertok) return false
//如果機器人沒有将ok放入方格中,則終止。
// 将機器人設定為正确的方向
// 将機器人最多轉4次或直到機器人在其前方有清楚的路徑
initialturncount = 1;
while (initialturncount <= 4 && hom.facingwall)
{ hom.turnleft();initialturncount++;}
// endwhile結束
this.display(); //顯示方格
hom.display(); //顯示機器人
while (hom.location != this.finish)
{ if (hom.facingwall)
{hom.turnleft();
if(hom.facingwall) { hom.turnright();hom.turnright();}
// endif結束
} // endif結束
hom.advance(onesquare);
hom.display;
} // endwhile結束
//機器人成功結束!
return true;
} //結束導航