第二章 第一個(gè)應(yīng)用

本章我們會(huì)開(kāi)發(fā)一個(gè)簡(jiǎn)單的游戲:點(diǎn)圖。隨著開(kāi)發(fā)流程我們會(huì)演示Squeak開(kāi)發(fā)過(guò)程中的大部分工具,演示開(kāi)發(fā)者之間如何交互。還會(huì)使用系統(tǒng)查看器,對(duì)象查看器,調(diào)試器,包管理器等工具。使用Smalltalk進(jìn)行開(kāi)發(fā)非常高效:其中大部分時(shí)間花在編寫代碼上,開(kāi)發(fā)流程的管理交給Squeak自動(dòng)完成。Smalltalk的語(yǔ)言簡(jiǎn)潔性和Squeak編程環(huán)境的豐富性。

2.1 點(diǎn)圖游戲

通過(guò)開(kāi)發(fā)一個(gè)簡(jiǎn)單的點(diǎn)圖游戲說(shuō)明如何使用Squeak的開(kāi)發(fā)工具。這個(gè)游戲的面板如圖。包含一系列的黃色塊組成,點(diǎn)擊其中的一個(gè),周圍的四個(gè)變成藍(lán)色,再次點(diǎn)擊,恢復(fù)到黃色。這個(gè)游戲的目的是盡可能多的轉(zhuǎn)換為藍(lán)色。

game

這個(gè)游戲包含兩類對(duì)象:一個(gè)是盒子對(duì)象,一個(gè)是100個(gè)獨(dú)立的塊對(duì)象。因此在Squeak需要通過(guò)代碼實(shí)現(xiàn)兩個(gè)類,一個(gè)是游戲盒子,一個(gè)是塊。接下來(lái)我們說(shuō)明如使用Squeak的開(kāi)發(fā)工具定義這兩個(gè)類。

2.2 創(chuàng)建新的類分類

我們將會(huì)在第一章介紹的系統(tǒng)查看器的基礎(chǔ)上,介紹如何定義新的類分類以及其中的類

Doit打開(kāi)系統(tǒng)查看器,右擊分類面板,選擇add item

sbe-quinto

在打開(kāi)的對(duì)話框中輸入新的分類名字SBE-Quinto。然后點(diǎn)擊accept或者輸入回車鍵。新的類分類創(chuàng)建。通常新的分類在最后,如何選擇了一個(gè)已存在的分類,那么將會(huì)創(chuàng)建在選擇的分類前面。

2.3 創(chuàng)建SEBCell類

這個(gè)新的分類中并沒(méi)有包含任何Class。在下面的主編輯區(qū)域包含了創(chuàng)建類的模板可以用作類快速創(chuàng)建模板

快速瀏覽其中的代碼,可以發(fā)現(xiàn)這個(gè)模板組織為發(fā)送消息給Object類,創(chuàng)建一個(gè)名為NameOfSubClass的子類。這個(gè)新的子類沒(méi)有任何變量,并且屬于SBE-Quinto類分類

我們就在這個(gè)模板的基礎(chǔ)上進(jìn)行修改創(chuàng)建我們需要的類

Doit 修改類創(chuàng)建模板
將Object名字替換為SimpleSwitchMorph
將NameOfSubClass替換為SBECell
添加mouseAction到類的實(shí)例變量中
修改結(jié)果如下

SBECell

修改的代碼包含一個(gè)Smalltalk表達(dá)式。發(fā)送消息給SimpleSwitchMorph類,要求創(chuàng)建一個(gè)子類SBECell。因?yàn)镾BECell并不存在,需要傳遞一個(gè)參數(shù)#SBECell作為類的名字。
然后在新創(chuàng)建的類中包含一個(gè)mouseAction實(shí)例變量,將用來(lái)定義塊應(yīng)該采取的動(dòng)作在受到點(diǎn)擊的時(shí)候

當(dāng)前只是輸入代碼,并沒(méi)有編譯生成任何類。需要使用accept進(jìn)行編譯保存

Doit編譯保存創(chuàng)建的類,

accept class

空白地方右擊選擇accept。
創(chuàng)建成功后,新創(chuàng)建的類將會(huì)顯示在系統(tǒng)查看器的第二欄。編輯區(qū)域顯示類的定義,下面提示輸入一些注釋。

這個(gè)區(qū)域叫做類注釋(class comment)。在大型項(xiàng)目開(kāi)發(fā)中代碼注釋非常重要,Smalltalk高度重視代碼的可讀性和注釋的詳細(xì)。也就是說(shuō)代碼應(yīng)該是自說(shuō)明的。類的注釋并不需要太詳細(xì)的描述,僅僅需要一些用來(lái)說(shuō)明這個(gè)類的用途。

SBE ok

Doit 對(duì)類進(jìn)行注釋

2.4 為類添加方法

接下來(lái)我們?yōu)樾聞?chuàng)建的類添加一些方法

Doit選擇協(xié)議面板中的all。
在編輯主區(qū)域顯示一個(gè)方法創(chuàng)建模板,選擇編輯器區(qū)域,修改代碼為下

initialize

Doit選擇accept保存創(chuàng)建的方法

讓我們逐行解釋這些代碼的意義

這個(gè)方法名稱是initialize.這個(gè)名稱的意義非常重要。通常一個(gè)類定義個(gè)initizlize方法,在創(chuàng)建一個(gè)對(duì)象后用來(lái)初始化對(duì)象的數(shù)學(xué)。所以當(dāng)執(zhí)行SBECell new后,將會(huì)發(fā)生initialize消息給類用來(lái)創(chuàng)建新的對(duì)象。初始化方法initialize將會(huì)用來(lái)初始化對(duì)象的狀態(tài),通常用來(lái)設(shè)置對(duì)象的實(shí)例變量,接下來(lái)我們將要說(shuō)明。

這個(gè)方法中第一句就是執(zhí)行父類SimpleSwitchMorph類的初始化方法,因此SimpleSwitchMorph中繼承的屬性將會(huì)被初始化。通常使用super initialize來(lái)初始化繼承的屬性。我們?cè)谶@里不知道SimpleSwitchMorph的初始化方法我們也不用關(guān)心,可以確定的是會(huì)初始化一些實(shí)例變量來(lái)保存默認(rèn)值,因此最好首先調(diào)用父類初始化避免未知的變量

方法的其余語(yǔ)句用來(lái)設(shè)置對(duì)象的數(shù)學(xué),self label:''首先設(shè)置對(duì)象的label為空字符串

表達(dá)式0@0 corner:16@16需要一些說(shuō)明。0@0表示一個(gè)xy坐標(biāo)系的原點(diǎn)未知,事實(shí)上這個(gè)語(yǔ)句發(fā)送@0消息到數(shù)字對(duì)象0,接下來(lái)數(shù)字0創(chuàng)建一個(gè)點(diǎn)Point類的實(shí)例(0,0)坐標(biāo)。接著發(fā)送消息corner:16@16用來(lái)創(chuàng)建以0@0和16@16的矩形。然后將這個(gè)矩形賦值給bounds變量。這個(gè)變量是繼承自父類。

需要注意的是Squeak屏幕原點(diǎn)在左上,y軸向下遞減。
其余的語(yǔ)句也是用來(lái)設(shè)置屬性。

2.5 探測(cè)對(duì)象

接下來(lái)創(chuàng)建一個(gè)對(duì)象來(lái)進(jìn)行觀察

Doit打開(kāi)workspce。輸入SBECell new右擊選擇inspect it。

打開(kāi)一個(gè)查看器,顯示了SBECell的實(shí)例變量列表,選擇其中的一個(gè)如bounds。它的值將會(huì)顯示在右側(cè)面板??梢允褂眠@個(gè)查看器修改實(shí)例變量的值

DOit 修改bounds的值為0@0 corner:16@16然后保存accept。
查看器下面是一個(gè)迷你workspace。經(jīng)常用來(lái)對(duì)當(dāng)前對(duì)象進(jìn)行測(cè)試使用

Doit在其中輸入se;f openInWorld 然后do it

接下來(lái)會(huì)在窗口創(chuàng)建一個(gè)塊,中擊顯示器控制,縮放大小,觀察查看器,可以看見(jiàn)bounds的值也會(huì)發(fā)生變化

2.6 定義SBEGame類

接下來(lái)我們創(chuàng)建另一個(gè)游戲類SBEGame

Doit使用系統(tǒng)查看器創(chuàng)建類SBEGame。
選擇SBE-Quinto類分類,編輯類創(chuàng)建代碼如下

SBEGame

代碼意思創(chuàng)建BorderedMorph的子類。Morph是所有圖形類的超級(jí)父類,而B(niǎo)orderedMorph類是帶有邊框的子類。
然后在SBEGame中定義一個(gè)初始化方法initialize

Doit選擇all協(xié)議,輸入下面的代碼

SBEGame-initialize

選擇accept it的時(shí)候,Squeak會(huì)說(shuō)明其中一些短語(yǔ)缺少定義,其中一個(gè)是cellsPerSide。提供了一些建議選項(xiàng)來(lái)修正拼寫錯(cuò)誤。

unknown selector

然而cellsPerSide并不是一個(gè)錯(cuò)誤,僅僅是一個(gè)未定義的方法,接下來(lái)選擇創(chuàng)建它。

Doit選擇第一個(gè)選擇,確認(rèn)事宜cellSPerSide.
接著提示cells也是未知的,提供了修正選項(xiàng)

Doit選擇declare instance聲明一個(gè)實(shí)例變量

接下來(lái)會(huì)說(shuō)明NeCellAt:at:也是未知的,同樣確認(rèn)。
然后再次查看整個(gè)對(duì)象 會(huì)發(fā)現(xiàn)修改后的保護(hù)cells變量。

那么分析下initialize方法
第一行聲明四個(gè)臨時(shí)變量 sampleCell width height n
作用域與生命周期僅僅在這個(gè)方法,臨時(shí)變量有助于代碼的可讀性。
smalltalk并不會(huì)區(qū)分常量與變量,事實(shí)上這四個(gè)變量是常量。接下來(lái)的幾行定義了這些常量

那么board是多大。需要容納足夠的cells和邊界框。那么其中包含多少個(gè)塊呢,我們并不知道,因此需要使用cellsPerSide來(lái)。

這個(gè)方法會(huì)在后面進(jìn)行定義,這種編寫代碼的方式是一種非常良好的方式,因?yàn)楫?dāng)我們進(jìn)行初始化的時(shí)候才知道我們需要什么,然后我們給出有意義的方法名稱,不需要打斷我們的思路

接下來(lái)會(huì)獲取cell的數(shù)量賦值給n.
接下來(lái)創(chuàng)建SBECell對(duì)象,賦值高度與寬度,
接下來(lái)設(shè)置buonds屬性。
最后實(shí)則cells變量屬性,使用Matrix。
需要使用兩個(gè)參數(shù)i j。
創(chuàng)建一個(gè)nxn矩陣初始化元素。初始化值依賴于坐標(biāo)信息。

接受到初始化方法的時(shí)候,需要抓住機(jī)會(huì)格式化輸出。選擇more...>prettyprint會(huì)進(jìn)行自動(dòng)排版,需要再次保存accept

2.7 保存方法到協(xié)議中

讓我們快速瀏覽下第三個(gè)面板。正如第一個(gè)面板用來(lái)保存類分類,第三個(gè)面板保存方法分類的協(xié)議。

如果只有少量的方法,不需要使用特定協(xié)議,這也是為什么僅僅提供all協(xié)議,

Doit有偶記選擇categorize all uncategorized來(lái)修正,移動(dòng)初始化方法到初始化協(xié)議中

Squeak如何識(shí)別合適的協(xié)議接口?通常Squeak并不會(huì)進(jìn)行識(shí)別,但是這種情況initialize是一個(gè)父類的方法,假設(shè)我們的初始化方法應(yīng)該屬于父類的同樣協(xié)議接口類

可以發(fā)現(xiàn)Squeak會(huì)自動(dòng)將initialize方法歸類到initialization協(xié)議,

smalltalk使用>>來(lái)定義一個(gè)方法所屬的類,可以使用SBEGame>>cellsPerSide。

從現(xiàn)在開(kāi)始,我們將會(huì)使用這種方法說(shuō)明類的方法,

使用SBEGANME>>initialize方法定義方法

依次定義cellsPerSide ,newCellAt ,toggleNeighboursOfCellAt等方法

Doit將最后一個(gè)方法拖放到game logic協(xié)議中

2.8 試試運(yùn)行

到此完成所有代碼編寫
包含兩個(gè)類和7個(gè)方法

Doit 在workspace中輸入SBEGame new openInWorld,然后選擇do it

也許可能出現(xiàn)一個(gè)錯(cuò)誤提示窗口,
這是需要調(diào)試器進(jìn)行修正

Doit點(diǎn)擊debug按鈕

debug

出現(xiàn)調(diào)試器界面,頂層窗口輸出運(yùn)行棧,顯示所有調(diào)用的方法。
選擇其中的一個(gè),將會(huì)顯示在中間。
其中錯(cuò)誤的代碼會(huì)高亮顯示

Doit選擇其中的第二條語(yǔ)句

調(diào)試器會(huì)顯示運(yùn)行的上下文如下。

debugger context

調(diào)試器的下方是兩個(gè)探測(cè)窗口,左側(cè)顯示接受消息的對(duì)象,可以查看對(duì)象的各個(gè)實(shí)例變量的值

右側(cè)查看對(duì)象執(zhí)行當(dāng)前方法的狀態(tài),可以查找方法的參數(shù)值與臨時(shí)變量

使用調(diào)試,可以逐行運(yùn)行代碼,查看對(duì)象的形參與臨時(shí)變量,最為驚奇的是可以在調(diào)試過(guò)程中修改代碼。因此編程過(guò)程在調(diào)試中完成。這種調(diào)試方式可以查看編寫方法特定運(yùn)行上下文與形參的運(yùn)行狀態(tài),

分析代碼中的bug。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,562評(píng)論 19 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 34,697評(píng)論 18 399
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,800評(píng)論 11 349
  • 重點(diǎn)掌握 3 類對(duì)象和方法 對(duì)象就是一個(gè)物體 類的獨(dú)特存在就是一個(gè)實(shí)例,對(duì)實(shí)例進(jìn)行操作叫做方法。方法可以應(yīng)用于類或...
    Coder大雄閱讀 1,368評(píng)論 0 2
  • 不安分似乎滲透在我的血液中。 99年大學(xué)畢業(yè),師范院校的同學(xué)們紛紛回到家鄉(xiāng)做老師,我卻離鄉(xiāng)背井從四川大...
    課間操閱讀 327評(píng)論 2 3

友情鏈接更多精彩內(nèi)容