none
請問有人有深入淺出 第五章:保護隱私的估價程式正解嗎? RRS feed

  • 問題

  • 主要是這樣

    一開始程式都跟書本的一樣,不過書本給了一個臭蟲,來說明封裝的意思

    一開始的程式如下

    類別DinnerParty.cs如下

    namespace Kathleen
    {
       
        class DinnerParty
        {
            public int NumberOfPeople;
            public decimal CostOfDecorations = 0;
            public decimal CostOfBeveragesPerPerson;
            public const int CostOfFoodPerPerson = 25;
            

            
            public void SetHealthyOption(bool HealthyOption)
            {
                if (HealthyOption)
                {
                    CostOfBeveragesPerPerson = 5.00M;
                }
                else
                {
                    CostOfBeveragesPerPerson = 20.00M;
                }

            }
            
            
            public void CalculateCostOfDecorations(bool Fancy)
            {
                if (Fancy)
                {
                    CostOfDecorations  = (NumberOfPeople * 15.00M) + 50.00M;
                }
                else
                {
                    CostOfDecorations = (NumberOfPeople * 7.50M) + 30.00M;
                }
                
            }

            public decimal  CalculateCost(bool HealthyOption)
            {
                
                decimal Totalcost = CostOfDecorations + ((CostOfBeveragesPerPerson +
                    CostOfFoodPerPerson) * NumberOfPeople) ;

                if (HealthyOption)
                {
                    return Totalcost * 0.95M;
                }
                else
                {
                    return Totalcost;
                }
            }

        }
    }

    From1.cs如下

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;

    namespace Kathleen
    {
        public partial class Form1 : Form
        {
            

            DinnerParty dinnerParty;
            public Form1()
            {
                InitializeComponent();
                dinnerParty = new DinnerParty() { NumberOfPeople = 5 };
                dinnerParty.SetHealthyOption(healthyBox.Checked);
                dinnerParty.CalculateCostOfDecorations(fancyBox.Checked);
                DisplayDinnerPartyCost();
            }

                private void fancyBox_CheckedChanged(object sender, EventArgs e)
                {
                    dinnerParty.CalculateCostOfDecorations(fancyBox.Checked);
                    DisplayDinnerPartyCost();
                }
                private void healthyBox_CheckedChanged(object sender, EventArgs e)
                {
                    dinnerParty.SetHealthyOption(healthyBox.Checked);
                    DisplayDinnerPartyCost();
                }
                private void numericUpDown1_ValueChanged(object sender, EventArgs e)
                {
                    dinnerParty.NumberOfPeople = (int)numericUpDown1.Value;
                    DisplayDinnerPartyCost();
                }    
                private void DisplayDinnerPartyCost()
                {
                    decimal Cost = dinnerParty.CalculateCost(healthyBox.Checked);
                    costLabel.Text = Cost.ToString("c");
                }
        }
    }

    但是在算總數時會有問題

    所以後面說了在類別中要用private

    所以加了幾行書上說的如下

    private int numberOfPeople;

    ...........

            public void SetPartyOptions(int people, bool fancy)
            {
                numberOfPeople = people;
                CalculateCostOfDecorations(fancy);
            }
            public int GetNumberOfPeople()
            {
               return numberOfPeople;
            }

    可是還是不行

    是不是還有那裡要加程式的

    2012年5月18日 上午 01:42

解答

  • 那你先好好的看完第五章

    看完之後你要的東西就會出現了


    以下為簽名檔,如果你愛拉椅子坐那就是你的問題。
    先查MSDN文件庫
    再用GOOGLE搜尋
    才到論壇來發問

    這是論壇不是技術支援中心
    沒有人得無償解答你的問題

    在標題或文章註明很急
    不會增加網友回覆速度

    • 已標示為解答 小義 2012年5月21日 上午 02:12
    2012年5月18日 下午 02:55
  • 看到你講的Bug

    我第一個直覺就是在numericUpDown1_ValueChanged事件再補上這兩個函式

                dinnerParty.CalculateCostOfDecorations(fancyBox.Checked);
                dinnerParty.SetHealthyOption(healthyBox.Checked);

            private void numericUpDown1_ValueChanged(object sender, EventArgs e)
            {
                dinnerParty.NumberOfPeople = (int)numericUpDown1.Value;
                dinnerParty.CalculateCostOfDecorations(fancyBox.Checked);
                dinnerParty.SetHealthyOption(healthyBox.Checked);
                DisplayDinnerPartyCost();
            }

    意為:

    確保每次客戶人數更動時,「飲料健康取向」和「裝飾取向」都被重新設定(書上也說了,人數變動時,裝飾費用並未被重新計算)

    雖然這樣是解決問題了,但應該不是本書主旨

    想先看書本解答,你可以翻到p214 ,如何解決在p213 (完整Source Code在:http://www.headfirstlabs.com/books/hfcsharp/)

    書本為了講解封裝,中間夾雜其他範例說明,所以你才會迫不及待上來問



    • 已編輯 Shadow .Net 2012年5月19日 上午 04:39
    • 已標示為解答 小義 2012年5月21日 上午 02:11
    2012年5月19日 上午 04:38

所有回覆

  • ..

    但是在算總數時會有問題

    所以後面...

    可是還是不行


    請問你所說有問題,是那裡有問題,錯誤信息是什麼,是那一行出錯誤信息?

    大家一齊探討、學習和研究,謝謝!
    MCSD, MCAD, MCSE+I, MCDBA, MCDST, MCSA, MCTS, MCITP, MCPD,
    MCT, Microsoft Community Star(TW & HK),
    Microsoft MVP for VB.NET since 2003
    My MSMVP Blog

    2012年5月18日 上午 04:01
  • 『還是不行』這句話真的很難懂. 發問請用明確的詞語 , 如果對發問的技巧不熟練, 請閱讀 [張貼文章應注意事項及應提供資訊].

    這本書我手上沒有, 不過依據你貼上來的章節名稱. 重點是要明白『不該開放的成員就不要開放』.

    也就是說一般我們對於存取修飾詞的使用優先順序大概是 private --> protected --> internalprotected internal-->public

    以你的例子, 一開始

            public int NumberOfPeople;
            public decimal CostOfDecorations = 0;
            public decimal CostOfBeveragesPerPerson;
            public const int CostOfFoodPerPerson = 25;

    這四個欄位成員都是 public, 也就是說其它的物件就有能力更改這四個欄位變數. 往下看到 Form1 Class中的

      public Form1()
            {
                InitializeComponent();
                dinnerParty = new DinnerParty() { NumberOfPeople = 5 };
                dinnerParty.SetHealthyOption(healthyBox.Checked);
                dinnerParty.CalculateCostOfDecorations(fancyBox.Checked);
                DisplayDinnerPartyCost();

          }

    這邊在建立了 DinnerParty 類別執行個體的時候, 給了一個初始值給 NumberOfPeople 欄位

       dinnerParty = new DinnerParty() { NumberOfPeople = 5 };

    再回到 DinnerParty 類別, 這個NumberOfPeople 基本上在設計者的原來的想法是可變動的, 也就是這個欄位可能是任何一個數字, 而且這個數字是由外部指定. 因此它絕對不是 private, 最起碼也要是 internal, 為了避免把你搞得更糊塗, 就用 public 吧.

    回到 Form1 類別的建構式中

                dinnerParty.SetHealthyOption(healthyBox.Checked);
                dinnerParty.CalculateCostOfDecorations(fancyBox.Checked);

    再回到 DinnerParty 類別的相關程式碼

    public void SetHealthyOption(bool HealthyOption)
            {
                if (HealthyOption)
                {
                    CostOfBeveragesPerPerson = 5.00M;
                }
                else
                {
                    CostOfBeveragesPerPerson = 20.00M;
                }

            }
            
            
            public void CalculateCostOfDecorations(bool Fancy)
            {
                if (Fancy)
                {
                    CostOfDecorations  = (NumberOfPeople * 15.00M) + 50.00M;
                }
                else
                {
                    CostOfDecorations = (NumberOfPeople * 7.50M) + 30.00M;
                }
                
            }

    在設計者的概念中, 他要限制 CostOfBeveragesPerPerson 等於 5 或 20, 所以寫了SetHealthyOption 方法, 依照傳入的bool值決定為 5 或 20.

    所以 CostOfBeveragesPerPerson 的存取控制就會變得嚴格, 因此要使用 private, 因為試想若是public 的狀況, 在 Form1 類別中這樣寫的話

         public Form1()
            {
                InitializeComponent();
                dinnerParty = new DinnerParty() { NumberOfPeople = 5 };
                dinnerParty.SetHealthyOption(healthyBox.Checked);
                dinnerParty.CalculateCostOfDecorations(fancyBox.Checked);

               dinnerParty.CostOfBeveragesPerPerson = 1000.0M;

                DisplayDinnerPartyCost();
            }

    這樣就完全破壞掉要限制 CostOfBeveragesPerPerson 不是 5 就是 20 的原則了, 這也就是封裝性被破壞掉.

    CalculateCostOfDecorations 這個方法也是有同樣的道理, 你可以自己思考看看.

    其它參考 MSDN 文件

    [存取修飾詞 (C# 程式設計手冊)]

    [存取範圍層級 (C# 參考)]


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    2012年5月18日 上午 04:07
    版主
  • Bill Chung 大大:
    打從心底裡佩服!
    如果他說的"有問題" 或 "不行" 不是你所想呢?

    大家一齊探討、學習和研究,謝謝!
    MCSD, MCAD, MCSE+I, MCDBA, MCDST, MCSA, MCTS, MCITP, MCPD,
    MCT, Microsoft Community Star(TW & HK),
    Microsoft MVP for VB.NET since 2003
    My MSMVP Blog

    2012年5月18日 上午 04:23
  • Dear Ken:

    那就只好繼續討論.不然怎麼辦.

    其實我上面忘了說一句話, 這位發問者恐怕看書是劃錯重點的, 這個章節的用意應該在於闡釋物件導向中的封裝, 也就是探討『成員隱藏與保護』,發問者似乎應該先從理解此原理著手, 而不是拘泥在程式碼的執行結果上.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2012年5月18日 上午 04:29
    版主
  • 設計是這樣的,流程是食物25元->選擇5元(總費用5%折扣)or20元飲料->選擇15元(加50元設置費)or7.5元(加30元設置費)裝飾

    前面貼的程式是可執行的,沒有執行上的問題,不過在執行的結果有問題,因為在改變人數時CalculateCostOfDecorations這一個沒有再被呼叫,要去點Fancy Decorations才會是正確的結果。

    所以後面書中有說要讓某些資料為類別所私有,所以要在DinnerParty中加上

    private int numberOfPeople;

    ...........

            public void SetPartyOptions(int people, bool fancy)
            {
                numberOfPeople = people;
                CalculateCostOfDecorations(fancy);
            }
            public int GetNumberOfPeople()
            {
               return numberOfPeople;
            }

    如果單純只加上上面的,如下

     class DinnerParty
        {
           
            private int numberOfPeople;
            public int NumberOfPeople;
            public decimal CostOfDecorations = 0;
            public decimal CostOfBeveragesPerPerson;
            public const int CostOfFoodPerPerson = 25;


            public void SetPartyOptions(int people, bool fancy)
            {
                numberOfPeople = people;
                CalculateCostOfDecorations(fancy);
            }
            public int GetNumberOfPeople()
            {
                return numberOfPeople;
            }

            public void SetHealthyOption(bool HealthyOption)

    ..............

    .....

    一樣可以執行,也不會有問題

    不過cost的結果還是不正確

    ps:我說的不行是這個,不好意思沒說明清楚

    現在想知道的是書中說的加上這幾行,是還有那應該要加程式的

    被版主說中了…現在想知道的是還要加什麼才有正確的結果

    很感謝版主的回覆,我會多看幾次你的回覆,還有連結的

    很多不懂,麻煩了

    謝謝^^

    2012年5月18日 上午 05:51
  • 一步一步來吧, 先找 Form1 類別中, 你既有的程式有哪些會呼叫到以下三個欄位 (變數) ?

            public int NumberOfPeople;
            public decimal CostOfDecorations = 0;
            public decimal CostOfBeveragesPerPerson;


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    2012年5月18日 上午 09:42
    版主
  • 呼叫NumberOfPeople

    dinnerParty = new DinnerParty() { NumberOfPeople = 5 };

    numericUpDown1_ValueChanged

    -----------------------------------------------------

    呼叫public decimal CostOfDecorations = 0;

    dinnerParty.CalculateCostOfDecorations(fancyBox.Checked);

    fancyBox_CheckedChanged

    -----------------------------------------------------

    呼叫public decimal CostOfBeveragesPerPerson;

    DisplayDinnerPartyCost()

    以上,有錯嗎?

    2012年5月18日 上午 09:58
  • 我只想問你有把第五章看完嗎????

    以下為簽名檔,如果你愛拉椅子坐那就是你的問題。
    先查MSDN文件庫
    再用GOOGLE搜尋
    才到論壇來發問

    這是論壇不是技術支援中心
    沒有人得無償解答你的問題

    在標題或文章註明很急
    不會增加網友回覆速度

    2012年5月18日 上午 10:58
  • 還在看下去
    2012年5月18日 上午 11:22
  • 那你先好好的看完第五章

    看完之後你要的東西就會出現了


    以下為簽名檔,如果你愛拉椅子坐那就是你的問題。
    先查MSDN文件庫
    再用GOOGLE搜尋
    才到論壇來發問

    這是論壇不是技術支援中心
    沒有人得無償解答你的問題

    在標題或文章註明很急
    不會增加網友回覆速度

    • 已標示為解答 小義 2012年5月21日 上午 02:12
    2012年5月18日 下午 02:55
  • 看到你講的Bug

    我第一個直覺就是在numericUpDown1_ValueChanged事件再補上這兩個函式

                dinnerParty.CalculateCostOfDecorations(fancyBox.Checked);
                dinnerParty.SetHealthyOption(healthyBox.Checked);

            private void numericUpDown1_ValueChanged(object sender, EventArgs e)
            {
                dinnerParty.NumberOfPeople = (int)numericUpDown1.Value;
                dinnerParty.CalculateCostOfDecorations(fancyBox.Checked);
                dinnerParty.SetHealthyOption(healthyBox.Checked);
                DisplayDinnerPartyCost();
            }

    意為:

    確保每次客戶人數更動時,「飲料健康取向」和「裝飾取向」都被重新設定(書上也說了,人數變動時,裝飾費用並未被重新計算)

    雖然這樣是解決問題了,但應該不是本書主旨

    想先看書本解答,你可以翻到p214 ,如何解決在p213 (完整Source Code在:http://www.headfirstlabs.com/books/hfcsharp/)

    書本為了講解封裝,中間夾雜其他範例說明,所以你才會迫不及待上來問



    • 已編輯 Shadow .Net 2012年5月19日 上午 04:39
    • 已標示為解答 小義 2012年5月21日 上午 02:11
    2012年5月19日 上午 04:38
  • 謝謝上面幾位大大的說明。我會先看下去在來解前面的問題

    謝謝

    2012年5月21日 上午 02:10