Time of Update: 2018-12-04
我們在構建一個回合制的系統每個對象的Go()方法都應該在我們的模擬器中的每一輪,或者叫做每一個回合中被調用。每一輪可以是任意的一段時間...比如說,一輪可以是10秒,或者60秒,或者是10分鐘。每一輪在動畫中表現為一幀,所以世界每一輪只改變一小點。關鍵是每一輪都會影響世界中的每一個對象。蜂巢每一輪檢查是否需要增加更多的蜜蜂。然後每隻蜜蜂運行一輪,向著目的地移動一點點距離或者是做一個小動作,並變老。然後每朵花運行一輪,產生一點花粉並變老。這正是World做的:它確定每一次World的Go()方法
Time of Update: 2018-12-04
我們在模擬器中用到的物件導向的一個重要原則就是封裝。看看你可不可以根據觀察我們已經寫過的類來找出每個類中兩個封裝的例子。下面是我們想出來的,你有沒有想出別的來?Hive:蜂巢的Locations字典是私人的;它給蜜蜂提供了一個添加蜂蜜的方法。Bee:蜜蜂的位置和年齡都是唯讀,這樣其他類將無法寫這些資料。Flower:花朵提供了採集花粉的方法;花朵的布爾型alive欄位是私人的。 問:為什麼不用foreach迴圈來移除死掉的花朵和退休的蜜蜂呢?答:foreach是用來迭代集合的,在其中無法移除
Time of Update: 2018-12-04
任何使用了Point類型的類檔案中都需要添加using System.Drawing;。③建立構造方法Flower類的構造方法需要接受一個Point來指明花朵的位置,還要接受一個Random類的執行個體。你應該可以用這些變數來設定花朵的位置,把年齡設定為0,設定花朵為活著的,並且把其花粉量設定為花朵的初始花粉量。由於劃分還沒有被採集過,所以要把這個變數設定對。最後,算出花朵的壽命。下面一行代碼可以協助你:lifeSpan = random.Next(LifeSpanMin, LifeSpan
Time of Update: 2018-12-04
最後的挑戰:開啟和儲存我們就快要可以著手於圖形的工作,給模擬器添加一些養眼的東西了。不過,首先還是給這一版再做一些別的事:允許載入,儲存,和列印蜜蜂的統計資料。①添加開啟,儲存和列印的表徵圖ToolStrip控制項有一個很實用的功能--它可以添加含有標準表徵圖的按鈕:建立,開啟,列印,剪下,複製,粘貼和協助。右擊處於表單設計器底部的ToolStrip並選擇“添加標準項”。點擊第一個表徵圖--它是“建立”--刪除它。留著餘下的三個。把其餘的不需要的按鈕也刪掉。②添加按鈕的事件處理方法這幾個按鈕被
Time of Update: 2018-12-04
我們已經有了四個核心類,我們需要做一些工作來把它們聯絡起來。遵循下面的步驟來做。但是要知道:在完成之前你必須修改幾乎每一個類的某些地方。①修改Bee來接受Hive和World的引用。現在有了Hive和World類,Bee對象需要知道它們。更新你的代碼來讓Bee在其構造方法中接受Hive和World的引用並且儲存這些引用來在稍後使用。②更新Hive來讓它接受一個World的引用就像Bee需要知道Hive一樣,Hive也需要知道World。更新Hive來讓它在構造方法中接受一個World的引用。你還
Time of Update: 2018-12-04
花之生死我們的花朵會經過一個基本的過程,生長,增加花粉,收穫花粉,並且最終死掉: 問:NectarHarvested變數在類中似乎除了給它增加值之外就沒有用到,這個變數是做什麼用的呢?答:好眼力!我們是提前做了計劃的,模擬器會監視花朵們一共產出了多少花粉,以供統計之用。所以暫時把它放一下,我們其他的類很快就會用到它。問:這些唯讀自動屬性是怎麼回事?答:記得第五章的隱藏私人變數嗎?這是個好傳統。花朵應該可以管理這些值,所以我們讓它們是唯讀。其他的對象,比如蜜蜂和蜂窩,應該可以讀取這些屬性而不可以
Time of Update: 2018-12-04
問:為什麼在GetLocation()方法中拋出了一個異常呢?答:為了防止傳入的參數不合法。這樣在傳入的參數不合法的時候就會爆出異常,可以協助你調試錯誤。問:既然我們不把蜜蜂繪製出來那為什麼還要把位置儲存在Point對象裡面呢?答:無論繪製與否,蜜蜂都需要記錄自己的位置。這樣就可以知道自己是否到達了目的地。問:為什麼要把位置儲存在Point裡面呢?Point不就是用來繪製的嗎?答:對的,所有的可視化控制項都是使用Point來儲存位置。然而,.NET如此使用它並不意味著我們不可以用它來儲存位置。
Time of Update: 2018-12-04
③更新World的代碼來把自己傳遞給Hive更新World的代碼來讓它在建立新Hive的執行個體的時候把自己的引用傳遞進去。 ④給Hive可以建立的蜜蜂數一個上限Hive類有一個MaximumBees常量,它決定了Hive可以支援多少蜜蜂(蜂巢內和蜂巢外都算)。現在Hive可以訪問World了,你應該可以運用這個約束了。 ⑤Hive建立蜜蜂的時候,讓World知道World類保持所有的存在的蜜蜂。當Hive建立幼蜂的時候,確保這個蜜蜂被添加到World保持的全域列表裡面去。
Time of Update: 2018-12-04
■如果在運行時某些事情出錯的話,任何語句都會拋出異常。■用try/catch塊來處理異常,未處理的異常會是你的程式停止並彈錯誤視窗。■try塊中的任何異常都會導致程式的執行跳轉到catch塊中的第一個語句。■Exception對象給你提供關於捕獲的異常的資訊。如果你在catch塊中聲明了Exception變數的話,該變數將會包含try塊中拋出的任何異常的資訊。■你可以捕獲很多種的異常。每種異常都是繼承自Exception類的。不要捕獲Exception,去捕獲特定種類的異常。■每個try塊可以
Time of Update: 2018-12-04
P.A.H.B(Programmers Against Homeless Bees)我們已經有了蜜蜂和充滿花粉的花朵。我們需要寫一些代碼來讓蜜蜂採集花粉,但是在此之前,蜜蜂最初是在哪兒被建立的呢?它們又把花粉帶到哪兒去?這時就用到了Hive類(蜂巢)。蜂巢不僅僅是蜜蜂們的歸宿。它內部有很多地點,每一個地點都對應著世界中的不同的座標。裡面有入口和出口,還有生育幼蜂的保育場所,還有把花粉轉化為蜂蜜的蜂蜜工廠。 蜂巢靠著蜂蜜來維持運行蜂巢扮演的另一個角色就是要用蜂蜜來維持蜂巢的運轉。蜂巢的運轉需要蜂
Time of Update: 2018-12-04
預防異常:實現IDisposable來自己做清理流很好用,因為它們已經有代碼來在它們被處置的時候關閉自己。但是如果你自己寫了類需要在被處置的時候做某些處理呢?如果你自己寫的類中的某些代碼可以再using中得以運行豈不是很酷?使用IDisposable介面就可以在C#中做到這一點。只有實現了IDisposable介面的類才可以using中使用,否則無法編譯。實現IDisposable介面,把你自己的清理代碼寫在Dispose()方法中,就象下面這樣: 我們可以使用多重的using語句。首先,使用
Time of Update: 2018-12-04
使用你學到的try/catch/finally的知識來改進Brian的借口管理器中的異常處理。①給Open按鈕的事件處理方法添加異常處理。唯寫一個彈出訊息框的try/catch就可以了。下面是你試圖開啟一個不是借口檔案的檔案時彈出的訊息框的樣子: ②還沒完事兒。運行程式,選擇一個檔案夾,在Description和Last Results欄中寫入資料,但是不要輸入Last Used date。現在選擇一個檔案夾並試著去儲存借口。得下面這個ArgumentOutOfRange異常了吧? 使用調試
Time of Update: 2018-12-04
編寫Hive的代碼是你的任務。①編寫Hive類的架構代碼就像編寫Flower類時一樣,你應該開始先給Hive類寫一個骨架代碼。類圖如右圖所示。把Honey設定為唯讀自動屬性,locations要是私人的,beeCount只在內部使用,所以也可以是私人的欄位。②定義Hive的常量初始蜜蜂數(6)需要一個常量,開始時候的蜂蜜數量(3.2),蜂巢最多可以承載的蜂蜜數(15),花粉向蜂蜜轉化率(0.25),最大蜜蜂數(8),可以生育幼蜂的最小蜂蜜數(4)。你需要給這些常量想出好的名字和適合的類型。關
Time of Update: 2018-12-04
蜂巢的Go()方法我們給Flower類寫了一個Go()方法,給Bee類也寫了一個Go()方法(雖然還有一些代碼要補充)。下面是Hive類的Go()方法: 不幸的是,這不太現實。很多時候,蜂后沒有時間來生育幼蜂。我們沒有一個QueenBee類,但是我們來假設蜂蜜足夠的時候會有十分之一的幾率去建立一隻幼蜂。我們可以如下來寫: 問:蜂巢可以建立無數的幼蜂?答:現在是可以的--當然,這不太現實。稍後我們會回來添加約束來只允許一定數量的蜜蜂同時存在於蜂巢中。問:我們不可以把Random的執行個體賦值給
Time of Update: 2018-12-04
我們準備好了來寫World類了有了Hive,Bee和Flower類,我們可以開始寫World類了。World負責協調模擬器中的每一個方面:記錄所有的蜜蜂,告訴蜂巢是否有足夠的控制項來容納更多的蜜蜂,定位花朵,等等: World對象維持所有事物的運行World對象的最重要的任務之一就是在模擬器中的每一輪去調用每一朵花,每一隻蜜蜂還有蜂巢的Go()方法。換句話說,World維持了模擬器世界中的生命的運轉。
Time of Update: 2018-12-04
問:using中只可以使用實現了IDisposable介面的對象?答:對。IDisposable就是設計來與using一起使用的。問:可以在using塊中寫任何代碼嗎?答:可以。Using的目的就是幫你把建立的對象最終處置掉。而你用這些對象做什麼完全是你的事兒。問:可以在using之外調用Dispose()嗎?答:可以。你可以不用using語句,自己手動去清除資源。而用了using則可以使你的代碼移動且防止你忘記了處置你的對象。問:你提到了try/finally塊。這意味著可以只有try和fin
Time of Update: 2018-12-04
Brian最終搞到了假期...現在Brian掌控了異常,他的工作進行的很順利而且他也得到了“應得的”(還是老闆允許的)假期了。 ...並且工作的事兒也在走上坡路!你的異常處理技巧不僅僅是防止了問題。還確保了Brian的老闆根本就不知道有問題出現過! 好的異常處理對於使用者是透明的。程式從不崩潰,即使有問題,也會被優雅的處理掉,不會出現讓人迷惑的錯誤資訊。
Time of Update: 2018-12-04
史上最差的catch塊:注釋如果你想的話一個catch塊可以保持程式一直運行。異常拋出了,你捕獲它,沒有關閉程式或者給出出錯資訊,只是繼續運行。但是有時候,沒有這種好事。看看下面的除法運算器,看起來很有趣,怎麼回事兒呢? 你應該處理異常,而不是把它遮掩起來你可以讓程式繼續運行不代表你處理了異常。上面的代碼中Divide()方法不會使得程式崩潰。但是如果別的方法調用這個方法並試圖列印結果呢?如果除數為零,那麼這個方法很有可能返回一個不正確的、未預期的值。你應該處理異常而不是添加註釋並掩蓋異常。如
Time of Update: 2018-12-04
暫時性的解決方案(短期內)是OK的有時你發現一個問題,知道它是個問題,但是不知道該如何處理。這種情況下,你可能會想要把它記錄下來,記下事情的狀況。這不如處理異常好,但是比什麼也不做強。下面是對除法計算機的一個暫時性的解決方案: 處理異常並不總是意味著去修複異常讓程式崩潰固然不好。但是不知道崩潰的原因或者不知道程式在對使用者的資料做什麼則更糟。所以你總是要處理可以預見的異常並記錄不可預見的異常。
Time of Update: 2018-12-04
我們已經有了四個核心類,我們需要做一些工作來把它們聯絡起來。遵循下面的步驟來做。但是要知道:在完成之前你必須修改幾乎每一個類的某些地方。①修改Bee來接受Hive和World的引用。現在有了Hive和World類,Bee對象需要知道它們。更新你的代碼來讓Bee在其構造方法中接受Hive和World的引用並且儲存這些引用來在稍後使用。 ②更新Hive來讓它接受一個World的引用就像Bee需要知道Hive一樣,Hive也需要知道World。更新Hive來讓它在構造方法中接受一個World的引用。你