1、单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,2021/10/3,#,项目三 面向对象程序设计,一、教学目标,终极目标:会用C#.net语言编写简单类,会用面向对象程序设计方法编写程序。,1/57,C#.net程序设计,课件中是以vs为界面介绍,开发环境假如是vs或vs,操作方法都基本一致,开发环境只是界面有少许不一样,基本知识相同,不影响读者学习本课程。,课件配套教材:c#.net程序设计,出版社:浙江大学出版社 主编:黎浩宏,课件例子源代码下载网址:,面向对象程序设计,促成目标:,1会用C#.net语言定义类以及实例化对象;,2会用C#.net语言定义
2、类组员数据、属性、方法。,3了解继承在C#语言中作用,学会经过派生类实例化对象调用父类中定义方法和属性。,4了解重载在C#语言中作用,学会在C#语言进行组员方法、结构方法重载。,3/57,项目三 面向对象程序设计,二、工作任务,用面向对象程序设计方法编写简单windows应用程序,4/57,项目三 面向对象程序设计模块1 园周长和面积,一、教学目标,了解和掌握面向对象三个基本特征封装、继承和多态;,了解和掌握C#语言中类和对象概念,并会在开发工具Visual Studio中建立类文件和实例化对象。,了解和掌握C#语言中结构方法概念和作用,并会在开发工具Visual Studio中类文件中建立类
3、结构方法。,5/57,模块1 园周长和面积,二、工作任务,设计一个圆类,利用面向对象方法类求圆周长和面积,程序运行时,出现如图3-1左图,单击“求圆周长和面积”按钮后,出现图3-1右图所表示界面,在label2上显示了圆半径、周长和面积。,6/57,7/57,模块1 园周长和面积,三、相关实践知识,开启visual studio 开发工具然后创建一个新c#.net windows应用程序。,(一)创建自定义类,1创建类,选择菜单【项目】|【添加类(C).】,出现如图2-2所表示界面,在“模板”中选择“类”,单击“添加”按钮。,8/57,模块1 园周长和面积,9/57,模块1 园周长和面积,此时
4、在”处理方案资源管理器”窗口中自动出现了一个类文件Circle.cs,10/57,模块1 园周长和面积,三、相关实践知识,开启visual studio 开发工具然后创建一个新c#.net windows应用程序。,(一)创建自定义类,1创建类,选择菜单【项目】|【添加类(C).】,出现如图2-2所表示界面,在“模板”中选择“类”,单击“添加”按钮。,11/57,模块1 园周长和面积,在代码编辑器窗口中,系统自动生成了一下代码:,using System;,using System.Collections.Generic;,using System.Text;,namespace Window
5、sApplication1,class Circle,在此,能够看到自动生成了一个类,类名为Circle,第6到第8行代码都是Circle类,这个类也在命名空间WindowsApplication1中。,12/57,模块1 园周长和面积,2编写类代码,在第7行和第8行代码(两个大括号)之间添加代码,,见代码。,13/57,模块1 园周长和面积,(二)设计窗体及相关控件属性,1设计窗体界面,窗体设计界面请参考图3-1左图所表示。,2添加控件和设置控件属性,窗体上共添加2个标签(Label),1个按钮(Button)和一个文本框(TextBox),依据表3-1格式进行设置各控件属性,控件属性取默认
6、值说明在表中不再说明。,14/57,模块1 园周长和面积,(三)编写事件处理方法,1编写按钮Click事件处理方法,程序代码以下:,private void button1_Click(object sender,EventArgs e),Circle circle=new Circle();,double r=Convert.ToDouble(textBox1.Text);,circle.setRadius(r);,label2.Text=string.Format(圆面积为:0:f2n圆周长为:1:f2,circle.getArea(),circle.getPerimeter();,第3行
7、代码创建了Circle类一个对象,第5行代码经过Circle类对象调用了类组员方法setRadius为圆半径设置了值。,15/57,模块1 园周长和面积,四、相关理论知识,(一)面向对象编程概述,面向对象程序设计(OOP)主要思想是将数据及处理这些数据操作都封装到一个称为类(Class)数据结构中。使用这个类时,只需要定义一个类变量即可,这个变量叫做对象(Object)。经过调用对象数据组员完成对类使用。对于类而言我们需要了解和掌握类、对象、属性、方法、封装、继承、多态这些基本概念,而类、对象、属性、方法在项目一中已经详细介绍过了,请参考相关内容,现在详细介绍封装、继承和多态这三个概念。,16
8、/57,模块1 园周长和面积,1封装,封装就是把对象属性和服务结合成一个独立系统单位,并尽可能隐蔽对象内部细节。,封装性是面向对象含有一个基本特征,其目标是有效实现信息隐藏标准。它是软件设计模块化、软件复用和软件维护一个基础。,如我们在模块一中定义Cilcel类,封装了两个组员变量pi和radius,三个组员方法。必须经过Circle对象引用其方法时,如circle.getArea()即求圆面积,而因为radius是类私有组员,不能经过circle.radius类存取圆半径,这就实现了数据组员隐藏。这就封装了圆这个类信息。,17/57,模块1 园周长和面积,2继承,面向对象程序设计允许编程人员
9、对类进行继承,继承后类仍含有被继承类特点,同时又出现新特点。在类继承中,被继承类称为基类(又称为父类),由基类继承类称为派生类(又称为子类)。派生类自动取得基类全部属性和方法,而且能够在派生类中添加新属性和方法。,如汽车类能够用于描述一辆普通汽车所共有和必须全部属性和方法,在需要定义奔弛汽车个性化属性和方法时,能够经过继承汽车类,添加飞驰汽车专有属性和方法,从而产生飞驰汽车类;一样方式还能够组成宝马汽车类。,18/57,模块1 园周长和面积,3多态,多态性指在普通类中定义属性或行为,被特殊类继承之后,能够含有不一样数据类型或表现出不一样行为。就是程序在运行时,会自动判断对象派生类型,并调用对应
10、方法。,面向对象各种多态方法使用,如动态绑定(dynamic binding)、重载(overload)等,提升了程序设计灵活性和效率。,19/57,模块1 园周长和面积,多态性使程序员能在一个类等级中使用相同方法多个版本,程序员能够集中精力开发可重用类和方向而无须过分担心名字冲突问题。如方法重载,就是多态一个应用,,如加法能够针对不一样类型计算加法,int add(int a,int b)和float add(float a,float b),这是两个针对整型和单精度数据加法方法,能够看到,方法名称完全相同,假如调用方法add(13,14),系统会依据参数类型自动调用int add(int
11、a,int b)方法。这就是多态一个应用。,20/57,模块1 园周长和面积,(二)类、对象、类组员,1定义类,C#.net语言类定义格式以下:,class 类名,数据组员,方法组员,21/57,模块1 园周长和面积,类范围由一对大括号来确定。类名能够自己任意取名,普通类名以大写字母开头。,类数据组员包含常量、类组员变量和属性,方法组员包含结构方法、方法、事件和索引器。如模块一中圆类定义了常量Pi,类组员变量radius,同时定义了三个方法。类常量和类组员变量在c#.net中也称为字段。,能够看到上面类定义格式中,出现两种访问修饰符,即类访问修饰符和类组员访问修饰符。其各自含义请看表3-2和表
12、3-3。,22/57,模块1 园周长和面积,表3-2 类访问修饰符,访问修饰符,意 义,public(公有),定义公有类,公有类能够在其它名字空间访问,Internal(内部),定义内部类,内部类只能在所在名字空间访问,其它命名空间中则不能访问。,23/57,模块1 园周长和面积,访问修饰符,意 义,public(公有),定义公有组员,公有数据组员允许在类内和类外访问,公有方法组员允许在类内和类外调用,private(私有),定义私有组员,私有数据组员只能在类内访问,类外则不允许访问私有数据组员,私有方法组员只允许在类内调用,在类外不能调用私有组员方法,protected(受保护),定义保护组
13、员,保护数据组员只能在类内和该类子类中访问,其它类则不能访问保护数据组员,保护方法组员只能在类内和该类子类中调用,其它类则不能访问保护组员方法,internal(内部),定义内部组员,内部数据组员只能在该类所在命名空间中访问,其它命名空间中则不允许访问内部数据组员,内部方法组员只允许在该类所在命名空间中调用,在其它命名空间中不能调用内部组员方法,24/57,模块1 园周长和面积,2创建对象,类建立好后,就能够定义和创建该类对象。,创建类对象能够分两步:,(1)先定义对象,格式:类名 对象名;,如:Circle circle1,circle2;/定义了类Circle两个对象,能够由用户自己为对象
14、命名。代码int i,j;大家都很清楚,是定义了两个整型变量i,j;我们知道int是一个数据类型,而定义对象也是如此,类其实是我们自己定义数据类型,对象名其实也是变量名,只不过我们将类变量名另外取了个名字,类变量就是对象。,25/57,模块1 园周长和面积,(2)然后创建类对象,类对象也称为类实例。,格式:对象名=new 类名();,如:circle1=new Circle();/创建Circle类一个对象,即创建了一个实例,以上两步也能够合并成一步。,格式:类名 对象名=new 类名();,如:Circle circle1=new Circlee();,26/57,模块1 园周长和面积,3类
15、实例组员,类实例组员也称为非静态组员,默认情况下类定义数据组员和方法组员都是实例组员。访问类实例数据组员和实例方法组员时,因为数据组员和方法组员都是属于类对象全部组员,所以一定要经过类对象访问类中定义数据组员和方法组员。,数据组员访问格式:,对象名.数据组员,其访问格式和访问对象属性格式完全相同,如circle.Pi就是访问圆Pi常量。,在类外部调用方法组员格式:,对象名.方法名(参数),假如定义方法没有参数,则调用时将不用参数,如circle.getPerimeter()。,27/57,模块1 园周长和面积,注意:千万不要用“类名.组员”格式类访问类数据组员或调用类组员方法。如Circle.
16、getPerimeter(),Circle.Pi则是错,再如我们要访问窗体标题栏信息时,我们都是用代码this.Text,不能用Form1.Text,this表示当前窗体对象,而Form1表示窗体类。,下面以一个详细例子进行分析讲讲解明,先创建一个新windows项目,在窗体上添加2个Label(标签),此时系统自动生成代码以下:,28/57,模块1 园周长和面积,using System;,.,namespace WindowsApplication1,public partial class Form1:Form,public Form1(),InitializeComponent();,
17、29/57,模块1 园周长和面积,这些代码我们再熟悉不过了,现在我们从类角度来分析这些代码,能够看到,系统自动生成了一个类Form1,这里说明一下,Form1是Form子类,即窗体类,窗体也是一个类,其范围是第5行代码到第11行代码。,30/57,模块1 园周长和面积,在第11和第12行代码之间添加一个ClassA类,代码以下:,using System;,.,namespace WindowsApplication1,public partial class Form1:Form,public Form1(),InitializeComponent();,31/57,模块1 园周长和面积,p
18、ublic class ClassA,public int a;/定义了一个公有整型组员变量a,,private int b;/定义了一个私有整型组员变量b,,internal int c;/定义了一个内部整型组员变量c,,public void SetA()/定义了一个公有组员方法,a=1;/正确,允许访问类本身公有组员,b=2;/正确,允许访问类本身私有组员,c3;/正确,允许访问类本身内部组员,32/57,模块1 园周长和面积,我们能够看到,在命名空间WindowsApplication1中包含了两个类,分别是窗体类Form1和ClassA类。,注意,ClassA类一定要写在Form1类
19、后面,c#.net要求必须将Form1类放在命名空间第一个类。,33/57,模块1 园周长和面积,在窗体Load事件中编写代码,其完整代码以下:,using System;,.,namespace WindowsApplication1,public partial class Form1:Form,public Form1(),InitializeComponent();,34/57,模块1 园周长和面积,private void Form1_Load(object sender,EventArgs e),ClassA ob=new ClassA();,ob.a=5;/正确,允许访问类公有组
20、员,ob.b=23;/错误,不允许访问类私有组员,ClassA.a=10;/错误,不能经过类直接访问类任何实例组员,ob.c=35;/正确,允许访问同一个命名空间内部组员,label1.Text=对象ob中数据组员a,c值分别是+ob.a+,+ob.c;,ob.SetA();/正确,允许访问类公有组员,label2.Text=对象ob中数据组员a,c值分别是+ob.a+,+ob.c;,35/57,模块1 园周长和面积,public class ClassA,public int a;,private int b;,internal int c;,public void SetA(),a=1;,
21、b=2;,c3;,36/57,模块1 园周长和面积,运行程序时犯错,原因就是在第15、16行代码犯错了,因为第14到第22行代码是在窗体类Form1中引用了ClassA类数据组员,事件Form1_Load是属于Form1类事件,对于类ClassA来说是该类外部,访问ClassA私有组员自然犯错了。假如将第15,16行代码删除,再运行程序,程序将能成功被运行,读者自己分析程序运行效果。,37/57,模块1 园周长和面积,第20行代码调用了ClassA类SetA()方法,因为是在ClassA类外部调用,所以要用ob.SetA();格式调用方法,我们在项目二模块7中调用方法时,都在同一个类中定义和调
22、用方法,故在项目二模块7中调用方法时,都不用“对象名.方法名()”格式调用,请读者仔细体会。,38/57,模块1 园周长和面积,这里必定有读者提出疑问,只在窗体上显示了对象ob组员变量a,c值,假如要显示私有组员变量b值,该怎么处理呢。我们此时就应该为ClassA类定义一个公共方法用来间接读取私有组员变量b值,在访问时,经过调用对应方法来读取私有变量b值,一样要定义一个公共方法用来为私有组员变量b赋值,从而能够在程序运行过程中改变私有组员变量b值。代码以下:,39/57,模块1 园周长和面积,using System;,.,namespace WindowsApplication1,publi
23、c partial class Form1:Form,private void Form1_Load(object sender,EventArgs e),ClassA ob=new ClassA();,ob.SetA();/正确,允许访问类公有组员,label1.Text=对象ob中数据组员b值是+ob.get_b();,ob.Set_b(50);/正确,经过该方法能够改变稀有组员变量值,label2.Text=对象ob中数据组员b值是+ob.get_b();,40/57,模块1 园周长和面积,public class ClassA,public int a;,private int b;,
24、internal int c;,public void SetA(),a=1;,b=2;,c3;,41/57,模块1 园周长和面积,public int get_b(),return b;,public void set_b(int n),b=n;,42/57,模块1 园周长和面积,第12和14行代码就经过调用方法get_b()间接读取了私有组员变量b值。,我们这个例子是将类ClassA直接写在Form1类后面,当然也能够用模块1中所介绍创建类方法进行定义ClassA类,这里这么组织代码,只是让读者更加好比较类之间关系。,43/57,模块1 园周长和面积,3类静态组员,代码MessageBox
25、Show(“信息”),我们经惯用到,这里我们知道MessageBox是类名,其实方法Show()是属于MessageBox类静态组员,静态组员和实例组员唯一区分就是在定义类组员时前面加了一个static关键字,要记住,静态组员是属于类,而不是属于对象,静态组员只能经过类来访问,不能够经过对象来访问。,44/57,模块1 园周长和面积,而在定义类时,类非静态组员方法能够访问类静态组员也能够访问类实例组员,而类静态组员方法只能访问类静态组员,而不能访问类实例组员。,以下面代码:,using System;,namespace WindowsApplication1,public partial
26、class Form1:Form,public Form1(),InitializeComponent();,45/57,模块1 园周长和面积,private void Form1_Load(object sender,EventArgs e),myClass A=new myClass();/定义对象A,A.a=10;/正确,只能经过对象访问静态公有组员变量a,A.b=20;/错误,不能经过对象直接访问静态公有组员b,myClass.a=20;/错误,不能经过类访问类中非静态公有组员,myClass.b=20;/正确,必须经过类访问类中静态公有组员,46/57,模块1 园周长和面积,clas
27、s myClass,public int a;/定义一个非静态组员变量,static public int b;/定义了一个静态组员变量,public void Fun1()/定义了一个非静态组员方法,a=10;/正确,非静态组员方法能够直接访问非静态组员,b=20;/正确,非静态组员方法能够直接访问静态组员,static public void Fun2()/定义了一个静态组员方法,a=10;/错误,静态组员方法不能够直接访问非静态组员,b=20;/正确,静态组员方法能够直接访问静态组员,相当,/于myClass.b=20,47/57,模块1 园周长和面积,类非静态组员属于类实例全部,每创建
28、一个类实例都在内存中为非静态组员开辟了一块区域。而类静态组员属于类全部,为这个类全部实例所共享。不论这个创建了多少个对象(实例),一个静态组员在内存中只占有一块区域。,48/57,模块1 园周长和面积,(三)this关键字,this 关键字表示为其调用方法当前实例,也就是类当前对象只能在类非静态方法组员中使用。,例3-1 该程序定义日期类(Date类),经过类来显示两个学生生日。,运行效果如图3-4所表示。,49/57,模块1 园周长和面积,50/57,模块1 园周长和面积,设计和编写代码方法以下:,步骤1:先创建一个新c#.net windows应用程序。依照模块1相关实践知识步骤,创建一个
29、Date类,然后编写Date类代码以下:,51/57,模块1 园周长和面积,using System;,using System.Collections.Generic;,using System.Text;,namespace WindowsApplication1,class Date,private int year;,private int month;,private int day;,52/57,模块1 园周长和面积,public void setDate(int y,int m,int d),this.year=y;,this.month=m;,day=d;,public str
30、ing ToDateString(),return string.Format(0/1/2,this.year,this.month,this.day);,53/57,模块1 园周长和面积,我们能够看到第13、14和第19行代码都有this关键字,这个this关键字表示是Date类当前对象。而第15行代码day前没有this关键字,其实是省略了this,this.year,this.month,day就是Date类类组员变量year,month,day。,步骤2:在窗体上添加两个Label控件,属性取默认值,然后编写窗体Load事件处理方法,代码以下:,54/57,模块1 园周长和面积,usi
31、ng System;,namespace WindowsApplication1,public partial class Form1:Form,public Form1(),InitializeComponent();,55/57,模块1 园周长和面积,private void Form1_Load(object sender,EventArgs e),Date birthday1,birthday2;,this.Text=”日期类窗体”;,birthday1=new Date();,birthday2=new Date();,birthday1.setDate(1985,10,2);,bi
32、rthday2.setDate(1986,4,28);,label1.Text=李明生日是:+birthday1.ToDateString();,label2.Text=萧微生日是:+birthday2.ToDateString();,56/57,模块1 园周长和面积,上面代码我们能够看到在第14行代码中有一个this关键字,我们以前说过,this就是当前窗体,这个this是当前窗体,就是类Form1当前对象,而当代码执行了17行代码时,依据以前知识,我们知道程序流程,会跳到Date类第11行代码执行,当执行Date类第13行代码“this.year=y;”时,这个this因为是在Date类中,而且是由Date类对象birthday1调用方法setDate,故表示Date类当前对象birthday1,一样,而当执行第18行代码,当程序执行Date类第13行代码“this.year=y;”时,这个this表示Date类当前对象birthday2。,57/57,






