第三章类和结构2Ch3类和结构3.1自定义类(class)和结构(struct)3.2属性和方法3.3类的继承与多态性3.4常用结构和类的用法3目标理解C#的类和对象使用C#构造函数和析构函数使用C#访问修饰符使用方法4对象属性型号价格里程行为起动停车行驶属性车轮数量档的数量行为加速换档刹车属性名称颜色品种行为摇尾巴吃东西犬吠类类与对象类:一组具有相同数据结构和相同操作的对象的集合。例如:汽车对象(实例):类的实例化。例如:卡车注意:要使用对象,必须先定义类,然后再创建对象。6类与对象类是C#中的一种结构,用于在程序中模拟现实生活的事物,类是对象的模板;对象是类的实例化。语法:[访问修饰符]class类名{//类的主体}示例:classEmployee{//类的主体}//成员变量//成员方法对象的生存周期对象在建立时分配了内存,创建对象实际上作了两个方面的工作:(1)使用new保留字要求系统分配内存;(2)使用构造函数初始化数据。销毁对象也是做了两个方面的工作:(1)释放占用的内存;(2)将分配给对象的内存归还给堆(Heap)。783.1.1类的定义和成员组织类:定义对象具有的特征(字段、属性等)和可执行的操作(方法、事件等)。自定义类的常用形式:[访问修饰符][static]class类名[:基类[,接口序列]]{[类成员]}类成员:包括字段、属性、构造函数、方法、事件、运算符、索引器、析构函数等。3.1.1类的组织1.类的声明用class定义类,声明类的形式为:[附加声明][访问修饰符]class类名称[:[基类][,接口序列]]{[字段声明][构造函数][方法][事件]}注意:[]中的内容可省或任选其一,当两者都有时,先基类后接口3.1.1类的组织(续)publicclassChild{privateintage;privatestringname;//不带参数的构造函数publicChild(){name=none;}//带参数的构造函数publicChild(stringname,intage){如果不指明,则默认为private3.1.1类的组织(续)this.name=name;this.age=age;}//输出方法publicvoidPrintChild(){Console.WriteLine({0},{1}yearsold.,name,age);}}publicclassProgram{3.1.1类的组织(续)publicstaticvoidMain(){//使用new关键字创建对象,new后是调用的构造函数Childchild1=newChild(ZhangSan,11);Childchild2=newChild(LiSi,10);Childchild3=newChild();//显示结果Console.Write(Child#1:);child1.PrintChild();Console.Write(Child#2:);child2.PrintChild();Console.Write(Child#3:);child3.PrintChild();3.1.1类的组织(续)Console.ReadLine();}}}输出结果:Child#1:ZhangSan,11yearsold.Child#2:LiSi,10yearsold.Child#3:none,0yearsold.3.1.2访问修饰符C#中有以下成员访问修饰符:Public(常用)任何外部的类都可以不受限制的存取这个类的方法和数据成员。private(常用)类中的所有方法和数据成员只能在此类中使用,外部无法存取。(默认)Protected除了让本身的类可以使用之外,任何继承自此类的子类都可以存取。Internal在当前项目中都可以存取。该访问权限一般用于基于组件的开发,因为它可以使组件以私有方式工作,而该项目外的其它代码无法访问。Protectedinternal只限于当前项目,或者从该项目的类继承的类才可以存取。Partial局部类型,类的定义和实现可以分布在多个文件中,但都要使用partial标注,基类只需要声明一次,若多次声明则必须完全一致。15访问修饰符2-1Teacher类private成员protected成员public成员internal成员Student类只有Student类在Teacher类都在同一程序集中,才可访问internal成员不可访问不可访问可以访问16partial修饰符:包含partial修饰符的类称为分部类。可将类的定义分布在多个文件中,编译器编译带有partial修饰符的类时,会自动将这些文件合并在一起。可隔离自动生成的代码和人工书写的代码。【例3-1】演示如何声明类、字段、构造函数和方法,同时说明如何实例化对象、如何使用分部类以及如何输出实例数据。3.1.2访问修饰符173.1.3静态成员和实例成员通过类名调用静态成员,通过实例名调用实例成员。1.static关键字表示类或成员加载到内存中只有一份,而不是有多个实例。当垃圾回收器检测到不再使用该静态成员时,会自动释放其占用的内存。可用于类、字段、方法、属性、运算符、事件和构造函数,但不能用于索引器、析构函数或者类以外的类型。静态字段有两个常见的用法:一是记录已实例化对象的个数,二是存储必须在所有实例之间共享的值。静态方法可以被重载但不能被重写,因为它们属于类,而不属于类的任何实例。183.1.3静态成员和实例成员2.静态类声明自定义类时如果加上static关键字,则该类就是静态类。静态类的主要特点:仅包含静态成员。无法实例化。这与在非静态类中定义私有构造函数可阻止类被实例化的机制相似。是密封的,因此不能被继承。不能包含实例构造函数,但可以包含静态构造函数。如果非静态类包含需要进行重要的初始化的静态成员,也应定义静态构造函数。3.1.4构造函数作用:构造函数是一个特殊的方法,用于在建立对象时进行初始化的动作。好处:确保每一个对象在被使用之前都适当地进行了初始化的动作。构造函数特点:1)每个类至少有一个构造函数。若程序代码中没有构造函数则系统会自动提供一个默认的构造函数。2)一个构造函数总是和它的类名相同。3)构造函数不包含任何返回值。4)构造函数总是public的。一般在构造函数中作初始化工作,对于执行过程用时比较长的程序代码,最好不要放在构造函数中。203.1.4构造函数和析构函数1.实例构造函数每创建一个对象,都会先通过new关键字指明调用的构造函数,这种构造函数称为实例构造函数。例如:Childchild=newChild();这条语句的Child()就是被调用的实例构造函数。21构造函数构造函数是类的一种特殊方法,每次创建类的实例都会调用它[访问修饰符]类名(){//构造函数的主体}语法:…//默认构造函数Employee(){_qualification=研究生;}…示例:3.1.4构造函数(续)1、默认构造函数(1)如果在类中不定义构造函数,系统会提供一个默认的构造函数。(2)默认构造函数没有参数。(3)默认构造函数自动将非静态成员初始化为:数值型:如int、double等,初始化为0。bool类型:初始化为false.引用类型:初始化为null。(4)如果自己定义了类的构造函数,则所有初始化工作由编程者自己完成。3.1.4构造函数(续)2.重载构造函数有时候可能会遇到这样的情况:在一个类中的多个方法中都要用到某一个数据成员,而该成员值必须从其他类中传递过来。这时,无参数的构造函数就不能胜任了,解决这个问题最好的办法就是:重载(Overloading)构造函数。3.1.4构造函数(续)usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceOverloadingExample{classProgram{publicProgram(){Console.WriteLine(null);}构造函数(续)publicProgram(stringstr){Console.WriteLine(str);}staticvoidMain(){Programaa=newProgram();Programbb=newProgram(Howareyou!);Console.ReadLine();}}}26演示:示例1构造函数2-2classEmployee{privatestring_name;privatechar_gender;privatestring_qualification;privateuint_salary;//默认构造函数publicEmployee(){_qualification=“研究生;}staticvoidMain(string[]args){//调用默认构造函数EmployeeobjEmployee=newEmployee();Console.WriteLine(“资格=+objEmployee._qualification);Console.WriteLine(“薪水=+objEmployee._salary);}}273.1.4构造函数和析构函数2.静态构造函数如果构造函数声明包含static修饰符,则为静态构造函数,否则为实例构造函数。创建第一个实例或引用任何静态成员之前,CLR会自动调用静态构造函数。例如:classSimpleClass{staticreadonlylongbaseline;staticSimpleClass(){baseline=DateTime.Now.Ticks;}}283.1.4构造函数和析构函数静态构造函数的特点:静态构造函数既没有访问修饰符,也没有参数。在创建第一个实例或引用任何静态成员之前,CLR会自动调用静态构造函数来初始化类。换言之,静态构造函数是在实例构造函数之前执行的。程序员无法直接调用静态构造函数,也无法控制何时执行静态构造函数静态构造函数仅调用一次。如果静态构造函数引发异常,在程序运行所在的应用程序域的生存期内,类型将一直保持未初始化的状态。293.1.3构造函数和析构函数3.默认构造函数和私有构造函数每个类要求必须至少有一个构造函数。如果代码中没有声明构造函数,则系统会自动为该类提供一个不带参数的空的构造函数,这种自动提供的构造函数称为默认构造函数。构造函数一般用public修饰符,但也可以用private创建私有构造函数。私有构造函数是一种特殊的构造函数,通常用在只包含静态成员的类中,用来阻止该类被实例化。如果不指定构造函数的访问修饰符,默认是private。但是,一般都显式地使用private修饰符来清楚地表明该类不能被实例化。4.重载构造函数构造函数可以被重载(Overloading),但不能被继承。30构造函数重载[访问修饰符]类名(){//构造函数的主体}语法:([参数列表])…//参数化构造函数Employee(stringstrQualification){_qualification=strQualification;}…示例:31构造函数2-2//默认构造函数privateEmployee(){_qualification=“研究生;}//参数化构造函数privateEmployee(stringstrQualification,stringstrName,chargender,uintempSalary){_qualification=strQualification;_name=strName;_gender=gender;_salary=empSalary;}publicstaticvoidMain(string[]args){//调用默认构造函数EmployeeobjGraduate=newEmployee();//调用参数化构造函数EmployeeobjMBA=newEmployee