1第3章面向对象编程基础1.理解基本概念2.理解类3.使用构造函数4.学习方法5.学习属性掌握2姓名、性别、年龄等:属性学习课程、参加社会活动:方法3.1面向对象编程概念1.对象——具有属性和操作(方法)的实体。属性:对象所处的状态方法:用于改变对象状态以达到特定的功能对象有一个唯一的标识名2.类——在对象之上的抽象,一种抽象的数据类型3.类是对象的模板,对象是类的具体化或类的实例示例:学生——类各位同学——对象3对象与类属性型号价格里程行为起动停车行驶属性车轮数量档的数量行为加速换档刹车属性名称颜色品种行为摇尾巴吃东西犬吠4面向对象程序设计在处理对象时,必须遵循的三个原则:1.封装用一个框架把数据和代码组合在一起,形成一个对象。类是支持对象封装的工具,对象则是封装的基本单元。2.继承利用继承可以创建分等级层次的类,继承是父类和子类之间共享数据和方法的机制,通常把父类称为基类,子类称为派生类。单继承:一个基类可以有任意数目的派生类,即一父多子多继承:一个类若有两个或两个以上的直接基类,即一子多父,称为多重继承,C#通过接口来实现3.多态性同一个操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。分为静态多态和动态多态沙发床沙发床汽车卡车轿车客车根据参数的差别直接调用对象方法根据基类间接调用对象方法53.2类3.2.1类的声明语法形式:[属性集信息][类修饰符]class类名[:类基]{[类主体]}1.属性集信息——是C#语言为程序中定义的各种实体附加一些说明信息,是C#语言的一个重要特征。属于高级编程内容,一般涉及不到。2.类名:唯一标识名3.类基:直接基类或接口。默认基类是object类,多个接口之间用逗号相隔4.类修饰符——访问权限、类的类型等,注意同一修饰符不允许出现多次,见表3.16表3.1类修饰符修饰符作用说明public表示不限制对类的访问。类的访问权限省略时默认为publicprotected表示该类只能被这个类的成员或派生类成员访问private表示该类只能被这个类的成员访问,很少用internal表示该类能够由程序集中的所有文件使用,而不能由程序集之外的对象使用new只允许用在嵌套类中,它表示所修饰的类会隐藏继承下来的同名成员abstract表示这是一个抽象类,该类含有抽象成员,因此不能被实例化,只能用作基类sealed表示这是一个密封类,不能从这个类再派生出其他类。显然密封类不能同时为抽象类示例:classStudent{//类主体}73.2.2类的成员类体(类主体)用于定义该类的成员用一对花括号{}括起来,由两部分组成:1.类体中以类成员声明形式引入的类成员包括:常数声明、字段声明、方法声明、属性声明、事件声明、索引器声明、运算符声明、构造函数声明、析构函数声明、静态构造函数、类型声明等2.直接从基类继承而来的成员8一、成员类型:(1)静态成员在字段、方法、属性、事件、运算符和构造函数声明中含有publicstatic修饰符(2)实例成员在字段、方法、属性、事件、运算符和构造函数声明中不含有publicstatic修饰符二、默认成员访问修饰符——private类成员注意点:9classProgram{classAClass{publicstaticintx=1;publicinty=2;}staticvoidMain(string[]args){AClassab=newAClass();Console.WriteLine(y={0},x={1},ab.y,AClass.x);}}101.常数声明语法形式:[属性集信息][常数修饰符]const类型标识符=常数表达式[,…]常数修饰符——new、public、protected、private、internalpublic:访问不受限制protected:访问仅限于包含类或从包含类派生的类型internal:访问仅限于当前程序集。private:访问仅限于包含类。类型——sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal、bool、string、枚举类型或引用类型。常数表达式的值类型应与目标类型一致,或者通过隐式转换规则转换成目标类型。11例如:classA_const{publicconstintX=10;constdoublePI=3.14159;//默认访问修饰符privateconstdoubleY=0.618+3.14;}注意1.常数表达式的值是一个可以在编译时计算的值注意2.常数声明不允许使用static修饰符,只能通过类访问。classTest{publicstaticvoidMain(){A_constm=newA_const();Console.WriteLine(“X={0},PI={1},Y={2}”,A_const.X,A_const.PI,A_const.Y);}}122.字段声明语法形式:[属性集信息][字段修饰符]类型变量声明列表;1.变量声明列表——标识符或用逗号“,”分隔的多个标识符,并且变量标识符还可用赋值号“=”设定初始值。2.字段修饰符——new、public、protected、private、internal、static、readonly、volatilestatic:静态变量。利用类直接访问静态变量,利用类的实例(对象)访问非静态变量readonly:只读变量,声明时或在构造函数中赋值,一旦赋值不可改变。与const常量不同,const常量编译时赋值计算。volatile:表示字段可能被多个并发执行的进程修改。13【例3.1】通过构造函数给只读字段赋值usingSystem;publicclassArea{publicreadonlydoubleRadius;//Radius是只读字段privatedoublex,y;publicdoubleSize;publicstaticdoubleSum=0.0;publicArea(){Radius=1.0;//通过构造函数对radius赋值}}classTest{publicstaticvoidMain(){Areas1=newArea();//s1.Radius=2;Console.WriteLine(Radius={0},Size={1},Sum={2},s1.Radius,s1.Size,Area.Sum);//静态字段通过类访问Area.Sum,实例字段通过对象访问s1.SizeConsole.Read();}}出错了!无法修改只读字段143.2.3构造函数和析构函数1.构造函数(1)实现对象初始化(2)分为实例构造函数和静态构造函数(3)函数调用时机:new1)实例构造函数的声明语法形式:[属性集信息][构造函数修饰符]标识符([参数列表])[:base([参数列表])][:this([参数列表])]{构造函数语句块}public与类名相同没有返回值构造函数重载:参数个数或类型不同调用基类同参数列表的构造函数调用本类同参数列表的构造函数151.构造函数修饰符——public、protected、internal、private、extern一般地,构造函数总是public类型的。如果是private类型的,表明类不能被外部类实例化。2.标识符([参数列表]opt)——构造函数名必须与这个类同名,无返回类型和返回值构造函数可以有0~n个参数——构造函数重载3.用new运算符创建一个类的对象时,类名后的一对圆括号提供初始化列表,系统根据这个初始化列表的参数个数、参数类型和参数顺序调用不同的构造函数。实例构造函数注意点:16classTest{staticvoidMain(){Timet1,t2,t3,t4;//对t1,t2,t3,t4分别调用不同的构造函数t1=newTime();t2=newTime(8);t3=newTime(8,30);t4=newTime(8,30,30);}}【例3.2】Time类的构造函数及其重载usingSystem;publicclassTime{privateinthour,minute,second;publicTime(){hour=minute=second=0;}publicTime(inth){hour=h;minute=second=0;}publicTime(inth,intm){hour=h;minute=m;second=0;}publicTime(inth,intm,ints){hour=h;minute=m;second=s;}}publicstringgetTime(){returnhour.ToString()+:+minute.ToString()+:+second.ToString();}Console.WriteLine(t1={0},t1.getTime());17【例3.3】构造函数初始化usingSystem;classPoint{publicdoublex,y;publicPoint(){x=0;y=0;}publicPoint(doublex,doubley){this.x=x;//当this在实例构造函数中使用时,this.y=y;//它的值就是对该构造的对象的引用}}classTest{publicstaticvoidMain(){Pointa=newPoint();Pointb=newPoint(3,4);//用构造函数初始化对象Console.WriteLine(a.x={0},a.y={1},a.x,a.y);Console.WriteLine(b.x={0},b.y={1},b.x,b.y);Console.Read();}}a.x=0,a.y=0b.x=3,b.y=418构造函数注意点:1.若类中没有提供构造函数,则CLR会自动提供一个默认的构造函数2.一旦类中提供了自定义的构造函数,系统则不提供默认的构造函数3.不必显示调用构造函数4.实例构造函数不能被继承19派生类构造函数的调用1.调用时机:创建派生类的对象时,即new2.构造函数不被继承3.派生类构造函数在执行前,首先显式或隐式地调用基类构造函数4.默认调用基类的无参数构造函数除非显式地指定调用有参数构造函数5.this关键字引用类的当前实例6.base关键字用于从派生类中访问基类的成员1.调用基类上已被其他方法重写的方法2.指定创建派生类实例时应调用的基类构造函数20【例3.4】派生类构造函数及其调用usingSystem;classPoint{privateintx,y;publicPoint(){x=0;y=0;Console.WriteLine(Point()constructor:{0},this);}publicPoint(intx,inty){this.x=x;this.y=y;Console.WriteLine(Point(x,y)constructor:{0},this);}}classCircle:Point{privatedoubleradius;publicCircle()//默认约定调用基类的无参构造函数Point(){Console.WriteLine(Circle()constructor:{0},this);}publicCircle(doubleradius):base(){this.radius=radius;Console.WriteLine(Circle(radius)constructor:{0},this);}publicCircle(intx,inty,doubleradius):base(x,y){this.radius=radius;Console.WriteLine(Circle(x,y,radius)constructor:{0},this);}}classTest{staticvoidMain(){Pointa=newPoint();Circleb=