实验04《OOP进阶》.docx
- 文档编号:11322428
- 上传时间:2023-02-26
- 格式:DOCX
- 页数:16
- 大小:251.05KB
实验04《OOP进阶》.docx
《实验04《OOP进阶》.docx》由会员分享,可在线阅读,更多相关《实验04《OOP进阶》.docx(16页珍藏版)》请在冰豆网上搜索。
实验04《OOP进阶》
实验4、OOP进阶
实验课时:
课内:
2;课外:
2
实验目的:
进一步熟悉面向对象的基本概念,特别是继承、派生、虚成员等概念;掌握面向对象程序设计的高级应用:
定义并运用基类、派生类,实现业务逻辑与应用界面的分离;学习并了解ListBox控件高级特性的用途及用法。
实验内容:
项目A:
类应用之服装销售
LookSharpFitnessCenter健身中心兼营服装销售业务。
该中心的服装销售涉及普通客户、会员客户两大类,不同的客户执行不同的折扣政策。
对于普通客户,可能给予一定的折扣。
而对于会员客户,则采取分级折扣,根据不同的会员级别给予固定的折扣比。
现在我们尝试着给该中心编写一个简单的服装销售登记及折扣处理程序。
该程序的运行时界面类似:
鉴于该中心在普通客户、会员客户上执行不同的折扣政策。
从长远看,这样的政策也很难说不再改变。
一旦政策改变,程序势必将进行必要的修改。
为便于程序今后的扩展、维护,我们可考虑采用继承的概念,在设计面向普通客户折扣处理类的基础上,通过继承派生出针对会员客户的特别服装折扣处理类。
这个程序总的设计思路为:
1.设计一个ClothingSale的基类,用以封装基本的销售数据及其处理功能,通过虚(virtual)方法实现普通客户的折扣处理
2.从ClothingSale基类派生出MemberClothingSale类,用以封装会员客户的销售数据及其处理功能,通过重写(override)虚方法实现会员客户的特别折扣处理
3.设计窗体界面,通过基本控件输入每一笔交易的数据。
由于尚未学习数据库的内容,我们暂且通过ListBox(列表框)控件来保存、显示所录入的每一笔交易(所售服装对象)。
除此之外,我们还结合运用Image(图像)组件、PictureBox(图片框)控件实现了服装照片的显示
考虑到这次实验的内容比较深入,本文档提供了绝大部分代码,希望大家在认真领会实验内容、代码的基础上自觉完成作业。
现在,请按照如下步骤完成程序设计:
1.创建项目
1在计算机D或E分区创建“你的文件夹”(类似“198009010101文立斌”)
2启动VisualStudio2010,在“你的文件夹”内创建名称类似“文立斌A”的C#Windows窗体应用程序项目,窗体名称改为类似“frm文立斌”
2.设计名为“ClothingSale”的普通客户销售处理类(基类)
在“解决方案资源管理器”中右键单击项目节点,然后依次单击【添加】→【类】,在项目中添加一个名称类似“ClothingSale.CS”的C#类文件,双击打开改文件,按如下要求在该文件中设计完成名为“ClothingSale”的类:
1在文件开始处添加namespace的引用代码,因为我们的程序将用到该namespace中的Image类来管理服装照片:
2声明如下实例字段:
✓discountRate为小数,例如:
0.1表示10%折扣,0.15表示15%折扣
✓extendedPrice=quantity*unitPrice*(1–discountRate)
✓您应该懂得为何要将这些字段(包括后面的若干字段)都声明为protecte——因为派生类中要能访问到它们!
3声明如下静态数组字段:
✓这个静态数组有点儿特别,用于保存与productId对应的商品的品名、计量单位及单位售价,而相关服装图片也是以商品的品名命名的。
之所以这样做,是因为我们希望模拟现实应用场景:
录入交易项目时,只需要输入productId就可以自动获得商品的品名、计量单位、单价乃至照片
✓当然,为实现以上功能,我们在在后面的代码中还设计了一个方法来初始化这个数组,并且在窗体的Load事件处理代码中调用这个方法完成初始化
✓因为每个productId对应的商品的品名、计量单位及单位售价都是完全相同的,因此,将这个数组声明为static是比较适当的选择
4声明如下静态字段:
✓salesCount、salesTotal分别用于累计每一笔交易的销售数量、金额,以随时了解总的销售量、销售额
✓您应该懂得为什么要将它们声明为static字段
5为productId定义相应属性,理解为什么属性要设置为public:
✓您应该懂得为什么要将属性声明为public
✓还要注意到:
我们将这个属性及相关的productId都设置成为byte而非decimal或float之类
6仿照以上代码并按如下要求定义其他属性:
quantity:
数量小数(int)可读写
unitPrice:
单价小数(decimal)只读
discountRate:
折扣率小数(decimal)可读写
extendedPrice:
金额小数(decimal)只读
salesCount:
数量静态小数(decimal)只读
salesTotal:
数量静态小数(decimal)只读
✓请仔细领会为何有的属性要定义为只读,有的又要定义为可读写,后面的两个属性又为何要定义成静态属性!
✓此外,请注意数量被声明为int类型!
7我们所创建的服装销售对象将通过ListBox控件来保存、显示。
为了使ListBox能完美地呈现所增加的每一个服装对象,我们需要再定义一个名为“销售摘要”的只读属性,以便ListBox能显示当前服装销售对象的相关数据,即:
可别小瞧这个ListBox,后面您将看到,它跟我们以前所做过的ListBox完全不一样:
这里的ListBox中所容纳的项目(Items)不是普普通通的string对象,而是这个程序中将要创建的ClothingSale或MemeberClothingSale对象,而显示的内容则是每个项目的相关数据(字符串)!
现在,我们先来定义这个名为“销售摘要”的只读属性再说:
请注意:
之所以将它定义为virtual,是因为在这个类的派生类中我们要重写(override)它!
另外,这里也用到string的静态方法Format来进行格式化输出——这将使得ListBox中显示摘要时能如下图那样很好地对齐:
8如前所述,商品的品名、单位、售价均保存在一个叫productList的二维静态数组中,用户输入productId后,我们要根据productId获得相应商品的品名以显示在窗体的控件中,因此我们需要定义“获取品名”的这样一个方法:
9根据productId获得商品售价的方法类似上述代码,现在请仿照以上代码定义一个名为“获取单价”的方法
10出于“用户友好”的考虑,每当用户输入商品的productId后,我们希望在窗体上通过PictureBox控件显示该商品的照片。
显然,我们也得定义一个名为“获取图片”的方法。
不过,这个方法可不像上面的方法那么简单!
我们的设计思路是:
✓为方便处理,商品照片的按“品名.PNG”的形式命名(例如,品名为“Sportssuit”的商品之照片为“Sportssuit。
PNG”)
✓商品照片文件保存在与解决方案(扩展名为.sln)文件相同的文件夹内——显然,您应该将从ftp下载到的图片文件复制到这个文件夹内
✓通过Image类的FromFile静态方法,可以轻松地根据磁盘图片文件创建Image对象,之后只需要将PictreBox的Image属性设置成这个Image对象就可以在窗体上显示服装照片
底下是“获取图片”方法的代码,这都是经常要用到的代码,希望您能好好领会:
11现在,我们得定义一个名为“计算金额”的虚(virtual)方法,该方法无形参无返回值,功能为根据当前所售商品的数量、单价、折扣率计算销售金额(extendedPrice),然后将数量、金额分别累加到salesCount、salesTotal字段内——代码很简单,就是按照前面的公式进行计算,因此请尝试着写出这简单的几句代码。
注意:
之所以将这个方法定义为虚方法,是因为会员客户折扣的计算方法不同,在派生类中我们要重写(override)这个方法
12还得定义一个名为“设置商品目录”的静态方法,该方法的功能为根据形参(数组)设置本程序所能销售的商品之品名、单位、售价。
由于将在类外调用这个方法来完成商品目录的初始化,因此应将该方法声明为public型:
13关于这个类,我们所要做的最后一件事,就是定义该类的构造函数:
3.设计名为“MemberClothingSale”的会员客户销售处理类(派生类)
在“解决方案资源管理器”中右键单击项目节点,然后依次单击【添加】→【类】,在项目中添加一个名称类似“MemberClothingSale.CS”的C#类文件,双击打开改文件,按如下要求在该文件中设计完成名为“MemberClothingSale”的类:
1作为基类“ClothingSale”的派生类,由于会员客户与普通客户只是折扣的处理上稍有不同,因此派生类MemberClothingSale”远没有基类复杂!
首先,请声明唯一的私有实例字段memberClass——虽然仅添加了这一个字段,但也较好地说明了继承的重要意义,这个类不仅继承了基类的所有成员,而且可以增加新的成员:
2显然,接下来您得为以上私有字段定义相应的属性,统一起见,请将属性名定义为“会员级别”,其访问方式为可读可写
3还记得基类中定义的只读属性“销售摘要”吗?
为了能与普通客户的交易记录区别开来,我们也得重写(override)基类中的这个属性。
代码是很简单的,我们只是在基类中“销售摘要”的后面,添加一个表示当前交易是面向会员交易的标志“【M】”:
4基类中有一个“计算金额”的方法,我们当时是将其定义为virtual方法的,现在我们当然应该override(重写)它,以根据如下规则,给不同级别的会员客户以不同的折扣率:
1级会员20%折扣
2级会员15%折扣
3级会员10%折扣
请按照这些规则重写这个方法,先根据会员级别(memberClass)确定折扣率,再计算当前交易的金额,最后将当前交易的数量、金额累加到salesCount、salesTotal字段中——代码真的不复杂!
5“MemberClothingSale.CS”的构造函数有点儿复杂,我们给出了这个函数的代码,但是希望您能理解这些代码:
4.设计窗体界面
截止当前,我们已经为LookSharpFitnessCenter健身中心设计完成服装销售处理用的两个类:
针对普通客户的基类ClothingSale和针对会员客户的派生类MemberClothingSale。
显然,接下来我们就该设计数据录入、显示的窗体,通过窗体控件录入、显示对普通客户或会员客户的交易记录。
最终的窗体界面类似:
该窗体中的控件包括:
1用于选择当前销售对象是否会员的两个RadioButton(单选按钮)控件
2用于滚动选择会员级别的一个NumericUpDown(循环数选)控件
3用于保存、显示所有销售项目(对象)的一个ListBox(列表框)控件
4用于显示服装照片的一个PictureBox(图片框)控件
5其他控件除两个Button(命令按钮)、两个GroupBox(分组框)、若干Label(标签)外,全部都是TextBox(文本框),不过有的TextBox应设计为只读而已!
5.编写事件处理方法代码
我们已经编写好后台处理用的两个类,也设计完成了前台数据录入、显示用的窗体界面,显然,现在要做的就是通过给窗体控件编写事件处理方法代码,来建立前台、后台的联系,以最终实现程序的功能:
1为窗体的Load事件编写如下代码:
2如前所述,我们希望每当用户输入商品的标识(代码)后,能在相关控件中自动显示商品的品名、单价及照片。
实现这个功能的比较合适的事件,无疑就是输入“商品标识”的TextBox的TextChanged事件,现在我们就来编写该事件处理的代码:
✓照抄并理解这些代码:
✓上面的代码已经获得用户输入的“商品标识”并存放在byte型变量bId内,现在请编写代码,依次调用ClothingSale类的静态方法“获取品名”、“获取单价”、“获取图片”获得与bId相应的商品品名、单价、照片,并设置于对应的TextBox或PictureBox中
✓编写代码,给控件设置默认值来初始化将要录入的交易记录,包括:
“是否会员”选项默认选择“否”,默认“折扣率”为0,默认“会员级别”设置为3,默认销售“数量”设置为1
编写以上代码后,运行程序时窗体截图类似:
3您或许注意到,按照程序的功能要求,依据客户的类别,普通客户时使用“折扣率”控件输入折扣率,而会员客户则只是选择“会员级别”,其折扣率是在MemberClosingSale类的“计算金额”中根据会员级别来确定的。
正因为此,窗体中提供了“折扣率”输入用的TextBox、“会员级别”选择用的NumericUpDown。
“用户友好”要求我们在用户选择“是”、“否”会员时,分别启用、禁用相关控件:
✓用户选择“是”会员时——
✓用户选择不是(“否”)会员时——
如何实现以上要求哩?
我们可以先编写一个名为“CustomerTypeChanged”的方法,在这个方法中检查用户在“是否会员”的选项中选择的是“是”还是“否”(提示:
Checked属性),并分别进行必要的设置,然后,在“是”、“否”两个RadioButton的CheckedChanged事件中调用这个方法。
这也给我们展示了不同的事件共享相同的事件处理方法的一个途径!
底下是代码的一个轮廓,请尝试着补充完整:
4现在用户已经可以通过窗体控件输入交易记录的相关数据,试运行一把,感觉应该算不错!
但是,还有一件重要的事情没做:
如何通过【增加】按钮将这个记录添加到ListBox中哩?
这个工作要考虑的首要问题,就是用户选择“是”、“否”会员时,要创建的分别是MemberClothingSale、ClothingSale两种对象。
我们提供若干代码给您,您应该尝试着将这些代码补充完整:
5我们已经做到用户输入一个有效的商品标识后,立即在PictureBox中显示对应的商品照片。
现在我们来做一个锦上添花的事:
每当用户在ListBox中选定一个项目时,其照片也能立即显示在这个PictureBox中:
6这个程序还剩下最后一个步骤,即给【退出】按钮的Click事件编写代码,询问用户是否结束程序的运行,必要时结束程序运行,代码如下,注意领会:
6.程序的调试及保存:
1单击【调试】→【启动调试】或【开始执行(不调试)】运行并测试程序
2单击【文件】→【全部保存】保存解决方案及项目(包括窗体)
3单击【文件】→【关闭解决方案】关闭当前解决方案
实验报告:
一、窗体截图:
二、主要代码(只需要你编写的代码):
三、问题简答(根据你的理解或查找MSDN作答):
●RadioButton和CheckBox的哪个属性表示相应的按钮已被选定或未被选定?
这个属性是什么类型的、取值又都有哪些?
●NumericUpDown用于在一定的范围内选择所需要的数值,那么,该控件默认的范围是多少?
上下限分别是通过哪个属性来调整?
此外,用户在这个控件中选定的数值又是通过哪个属性来体现?
●Image属于哪个namespace?
它是静态类还是实例类?
这个类的FromFile方法是静态方法还是实例方法?
●MessageBox.Show方法是静态方法还是实例方法?
其返回值是什么类型的?
其用于设置要显示的按钮、图标的形参又都是什么类型的?
四、提交实验结果:
●将本文档复制到“你的文件夹”内
●删除“你的文件夹”内每个项目文件夹中的BIN、OBJ子文件夹
●右键单击“你的文件夹”,通过上下文菜单(快捷菜单)中的RAR程序,将该文件夹内的全部内容压缩成名称类似“198009010101文立斌.RAR”的文件,然后提交到指定FTP目录
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- OOP进阶 实验 04 OOP 进阶