Book Head First C# - 我无法通过关于封装的章节

时间:2014-04-24 21:08:42

标签: c# properties encapsulation

我刚刚开始学习C#,我已经遇到了封装问题。 在书中有一个演练如何构建一个应用程序 - 它并不重要。

我有两节课: Form1中:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Farmer farmer;

        public Form1()
        {
            InitializeComponent();
            farmer = new Farmer(15, 30);
        }

        private void calculateButton_Click(object sender, EventArgs e)
        {
            Console.WriteLine("I need {0} bags of feed for {1} cows.", farmer.BagsOfFeed, farmer.NumberOfCows);
        }

        private void cowCount_ValueChanged(object sender, EventArgs e)
        {
            farmer.NumberOfCows = (int)cowCount.Value;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            farmer.BagsOfFeed = 5;
        }
    }
}

班级农夫:

    namespace WindowsFormsApplication1
{
    class Farmer
    {
        public int BagsOfFeed;

        private int feedMultiplier;
        public int FeedMultiplier { get { return feedMultiplier; } }

        private int numberOfCows;
        public int NumberOfCows
        {
            get
            {
                return numberOfCows;
            }
            set
            {
                numberOfCows = value;
                BagsOfFeed = FeedMultiplier * numberOfCows;
            }
        }

        public Farmer(int numberOfCows, int feedMultiplier)
        {
            this.feedMultiplier = feedMultiplier;
            NumberOfCows = numberOfCows;
        }

    }
}

由于Form1类中的button1_click方法,应用程序无法正常工作。在书中写道,我应该将公开的BagsOfFeed字段更改为属性 - 所以我这样做:

public int BagsOfFeed { get; set; }

之后有文字:

  

现在你有了一个属性而不是一个字段。当C#看到这一点时,它的工作方式与您拥有的完全相同   使用了一个支持字段(如公共NumberOfCowsproperty后面的私有numberOfCowsbe)。

     

尚未解决我们的问题。但是有一个简单的解决方法 - 只需要制作   它是一个只读属性:尝试重建代码 - 你会得到一个错误   在按钮上的行设置BagsOfFeedtelling你那个   set accessor无法访问。你不能在外面修改BagsOfFeedfrom   Farmerclass - 你需要删除该行以获得你的   要编译的代码,所以删除按钮和事件处理程序   形成。现在你的Farmerclass被封装得更好了!

我真的不明白发生了什么 - 我的应用程序仍然和以前一样。我想我必须以某种方式将此属性设置为只读属性,因为在本文中说(但没有解释)。但是怎么样? 我试图删除实现的设置部分,但后来我有一个错误:

  

错误1'WindowsFormsApplication1.Farmer.BagsOfFeed.get'必须声明一个正文,因为它没有标记为abstract或extern。自动实现的属性必须定义get和set访问器。 C:\ Users \ Dess \ documents \ visual studio 2013 \ Projects \ HeadFirst \ WindowsFormsApplication1 \ Farmer.cs 12 33 ExerciseCowCount

我还有一个问题 - 普通字段public int Variablepublic int Variable{get;set;}之间的区别是什么?

1 个答案:

答案 0 :(得分:2)

而且我真的不明白发生了什么 - 我的申请仍然和以前一样。

确实如此,但不同。首先,您在课程中有一个public int BagsOfFeed,可以从程序中的任何位置访问和更改。

这样可行:

farmer.BagsOfFeed= 1;
int i = farmer.BagsOfFeed; // i is now 1
farmer.BagsOfFeed= 5;
i = farmer.BagsOfFeed; // i is now 5

一般原则是不使用公共字段,因为可以在程序中的任何位置更改它们。有些情况(我知道这本书至少解释了一个例子,关于计算方成本,如果我没记错的话)可能会弄乱程序的输出。

为了防止这种情况发生,我们使用属性来封装字段。

  

尚未解决我们的问题。但是有一个简单的解决方法 - 只需要它   只读属性:尝试重建代码 - 您将收到错误   在设置BagsOfFeedtelling设置访问者的按钮中   无法访问。您无法在BagsOfFeedfrom之外修改Farmerclass

您的意图是让您的财产只读:

public int BagsOfFeed
{
    get;
    private set;
}

请注意private之前的set。这样做是为了使属性可以从任何地方获取,但只能从该类内部设置。 BagsOfFeed现已封装。

在此特定示例中,该属性省略了实施farmer.getBagsOfFeed()farmer.setBagsOfFeed(n)等方法的需要