我刚刚开始学习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 Variable
和public int Variable{get;set;}
之间的区别是什么?
答案 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)
等方法的需要