C面向对象基础学习教案

上传人:莉**** 文档编号:110294085 上传时间:2022-06-18 格式:PPTX 页数:79 大小:445.97KB
返回 下载 相关 举报
C面向对象基础学习教案_第1页
第1页 / 共79页
C面向对象基础学习教案_第2页
第2页 / 共79页
C面向对象基础学习教案_第3页
第3页 / 共79页
点击查看更多>>
资源描述
会计学1C面向对象基础面向对象基础(jch)第一页,共79页。类就是(jish)一种数据结构,它定义数据和操作这些数据的代码。3.2.1 类的声明语法形式:属性集信息 类修饰符 class 类名 : 类基 类主体 其中: 属性集信息是C#语言提供给程序员的,为程序中定义的各种实体附加一些说明信息,这是C#语言的一个重要特征。 类修饰符可以是表3.1所列的几种之一或是它们(t men)的有效组合,但在类声明中,同一修饰符不允许出现多次。第1页/共79页第二页,共79页。修 饰 符作 用 说 明public表示不限制对类的访问。类的访问权限省略时默认为 publicprotected表示该类只能被这个类的成员或派生类成员访问private表示该类只能被这个类的成员访问internal表示该类能够由程序集中的所有文件使用,而不能由程序集之外的对象使用new只允许用在嵌套类中,它表示所修饰的类会隐藏继承下来的同名成员abstract表示这是一个抽象类,该类含有抽象成员,因此不能被实例化,只能用作基类sealed表示这是一个密封类,不能从这个类再派生出其他类。显然密封类不能同时为抽象类第2页/共79页第三页,共79页。类的定义包括类头和类体两部分,其中类体用一对大花括号 括起来,类体用于定义该类的成员。语法形式: 类成员声明 类成员由两部分组成,一个是类体中以类成员声明形式引入的类成员,另一个则是直接从它的基类继承而来的成员。类成员声明主要包括:常数声明、字段声明、方法声明、属性声明、事件声明、索引器声明、运算符声明、构造函数声明、析构函数声明、静态(jngti)构造函数、类型声明等。第3页/共79页第四页,共79页。语法形式:属性集信息 常数修饰符 const 类型 标识符 = 常数表达式 , 其中: 常数修饰符new、public、protected、internal、private。 类型sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal、bool、string、枚举类型或引用类型。常数表达式的值类型应与目标类型一致(yzh),或者通过隐式转换规则转换成目标类型。例如:class A_const public const int X=10; const double PI=3.14159; / 默认访问修饰符,即约定为private const double Y= 0.618+3.14;第4页/共79页第五页,共79页。常数声明(shngmng)不允许使用static修饰符,但它和静态成员一样只能通过类访问。例如:class Test public static void Main( ) A_const m = new A_const ( ); Console.WriteLine (X=0, PI=1,Y=2, A_const.X , A_const.PI A_const.Y); 第5页/共79页第六页,共79页。2字段声明语法形式:属性集信息 字段修饰符 类型 变量声明列表(li bio);其中: 变量声明列表(li bio)标识符或用逗号“,”分隔的多个标识符,并且变量标识符还可用赋值号“=”设定初始值。例如:class A int x=100 , y = 200; float sum = 1.0f; 字段修饰符new、public、protected、internal、private、static、readonly、volatile。第6页/共79页第七页,共79页。【例3.1】 通过(tnggu)构造函数给只读字段赋值using System;public class Areapublic readonly double Radius; / Radius是只读字段是只读字段private double x, y ;public double Size ; public static double Sum=0.0 ;public Area ( ) Radius=1.0; / 通过构造函数对通过构造函数对radius赋值赋值class Testpublic static void Main( )Area s1 = new Area( );Console.WriteLine (Radius=0, Size=1,Sum=2,s1.Radius,s1.Size , Area.Sum);/ 静态字段通过类访问静态字段通过类访问(fngwn)Area.Sum,实例字段通过对象访问,实例字段通过对象访问(fngwn)s1.SizeConsole.Read ();第7页/共79页第八页,共79页。 无论是静态字段还是实例字段,它们的初始值都被设置(shzh)成字段类型的默认值。如果字段声明包含变量初始值设定,则在初始化执行期间相当于执行一个赋值语句。对静态字段的初始化发生在第一次使用该类静态字段之前,执行的顺序按静态字段在类声明中出现的文本顺序进行。当实例字段的初始化发生在创建一个类的实例时,同样是按实例字段在类声明中的文本顺序执行的。第8页/共79页第九页,共79页。第9页/共79页第十页,共79页。1构造函数提供(tgng)了实现对象进行初始化的方法,这就是构造函数。在C#中,类的成员字段可以分为实例字段和静态字段,与此相应的构造函数也分为实例构造函数和静态构造函数。第10页/共79页第十一页,共79页。(1)实例构造函数的声明语法形式:属性集信息 构造函数修饰符 标识符 ( 参数列表 ) : base ( 参数列表 ) : this ( 参数列表 ) 构造函数语句块 其中:构造函数修饰符public、protected、internal、private、extern。一般地,构造函数总是public类型的。 标识符(参数列表 opt)构造函数名,必须与这个类同名,不声明返回类型,并且没有任何返回值。它与返回值类型为void的函数不同。构造函数重载(zhn zi)。 用new运算符创建一个类的对象时,类名后的一对圆括号提供初始化列表,这实际上就是提供给构造函数的参数。系统根据这个初始化列表的参数个数、参数类型和参数顺序调用不同的构造函数。第11页/共79页第十二页,共79页。using System;public class Timeprivate int hour, minute, second;public Time ( ) hour=minute=second=0;public Time (int h)hour=h;minute=second=0;public Time (int h, int m)hour=h;minute=m;second=0;public Time (int h, int m, int s) hour=h;minute=m;second=s;class Teststatic void Main() Time t1, t2, t3, t4 ; / 对t1, t2, t3, t4分别调用(dioyng)不同的构造函数t1= new Time (); t2 = new Time(8);t3 = new Time(8, 30);t4 = new Time(8,30,30);【例3.2】 Time类的构造函数及其重载(zhn zi)。第12页/共79页第十三页,共79页。实例对象创建(chungjin)时,根据不同的参数调用相应的构造函数完成初始化。using System;class Point public double x, y; public Point( ) x = 0; y = 0; public Point(double x, double y) this.x = x; / 当this在实例构造函数中使用时, this.y = y; / 它的值就是对该构造的对象的引用 class Testpublic static void Main( ) Point a = new Point( ); Point b = new Point(3, 4); / 用构造函数初始化对象Console.WriteLine (a.x=0, a.y=1, a.x, a.y );/a.x=0, a.y=0Console.WriteLine (b.x=0, b.y=1, b.x, b.y );/b.x=3, b.y=4Console.Read (); 第13页/共79页第十四页,共79页。派生类构造函数的调用(dioyng)次序【例3.4】 派生类构造函数及其调用(dioyng)。using System;class Pointprivate int x, y;public Point()x = 0; y = 0;Console.WriteLine (Point() constructor : 0 , this );public Point(int x, int y)this.x = x; this.y = y; 第14页/共79页第十五页,共79页。Console.WriteLine (Point(x,y) constructor : 0 , this ); class Circle : Pointprivate double radius;public Circle () / 默认约定(yudng)调用基类的无参构造函数Point() Console.WriteLine (Circle () constructor : 0 , this );public Circle (double radius ): base ( )this.radius = radius;Console.WriteLine (Circle (radius) constructor : 0 , this );public Circle (int x, int y, double radius ): base (x, y ) this.radius = radius;Console.WriteLine (Circle (x, y, radius) constructor : 0 , this );class Test static void Main() Point a = new Point(); Circle b = new Circle (3.5); Circle c = new Circle (1, 1, 4.8); Console.Read (); 第15页/共79页第十六页,共79页。程序运行结果(ji gu)如下:第16页/共79页第十七页,共79页。(2)静态构造函数的声明语法形式:属性(shxng)集信息 静态构造函数修饰符 标识符()静态构造函数体其中: 静态构造函数修饰符 extern static 或者static extern 。如果有extern修饰,则说明这是一个外部静态构造函数,不提供任何实际的实现(shxin),所以静态构造函数体仅仅是一个分号。 标识符( ) 是静态构造函数名,必须与这个类同名,静态构造函数不能有参数。 静态构造函数体静态构造函数的目的是对静态字段的初始化,所以它只能对静态数据成员进行初始化,而不能对非静态数据成员进行初始化。第17页/共79页第十八页,共79页。关于构造函数,还有几点请注意: : base ( 参数列表 opt ) 表示调用直接基类中的实例构造函数。 : this ( 参数列表 opt ) 表示调用该类本身(bnshn)所声明的其他构造函数。 构造函数语句块既可以对静态字段赋值,也可以对非静态字段进行初始化。但在构造函数体中不要做对类的实例进行初始化以外的事情,也不要尝试显式地调用构造函数。 实例构造函数不能被继承。如果一个类没有声明任何实例构造函数,则系统会自动提供一个默认的实例构造函数。第18页/共79页第十九页,共79页。【例3.5】 静态(jngti)构造函数。using System;class Screen static int Height; static int Width; int Cur_X , Cur_Y ; static Screen ( ) / 静态(jngti)构造函数,对类的静态(jngti)字段初始化 Height=768; Width=1024; 关于静态构造函数,请注意: 静态构造函数是不可继承的,而且不能被直接调用。 只有创建类的实例或者引用类的任何静态成员时,才能激活静态构造函数,所以在给定的应用程序域中静态构造函数至多被执行一次。 如果(rgu)类中没有声明静态构造函数,而又包含带有初始设定的静态字段,那么编译器会自动生成一个默认的静态构造函数。第19页/共79页第二十页,共79页。语法形式:属性集信息 extern 标识符 ( ) 析构函数体其中:标识符必须与类名相同,但为了区分构造函数,前面需加“”析构函数不能写返回类型(lixng),也不能带参数,因此它不可能被重载,当然它也不能被继承,所以一个类最多只能有一个析构函数。第20页/共79页第二十一页,共79页。关于析构函数,请注意: 析构函数不能由程序显式地调用,而是由系统在释放对象时自动调用。 如果对象是一个派生类对象,那么在调用析构函数时也会产生链式反应,首先执行派生类的析构函数,然后执行基类的析构函数,如果这个基类还有自己的基类,这个过程就会不断重复,直到调用Object类的析构函数为止,其执行顺序正好(zhngho)与构造函数相反。第21页/共79页第二十二页,共79页。C#没有全局常数、全局变量和全局方法,任何事物都必须封装在类中。通常,程序的其他部分通过类所提供的方法与它进行互操作。对方法的理解可以从方法的声明、方法的参数、静态方法与实例方法、方法的重载与覆盖等方面切入。3.3.1 方法的声明方法是按照一定格式组织的一段程序代码,在类中用方法声明的方式来定义。语法(yf)形式:属性集信息 方法修饰符 返回类型 方法名 ( 形参表 ) 方法体第22页/共79页第二十三页,共79页。表3.2 方法(fngf)修饰符修 饰 符作 用 说 明new在一个继承结构中,用于隐藏基类同名的方法public表示该方法可以在任何地方被访问protected表示该方法可以在它的类体或派生类类体中被访问,但不能在类体外访问private表示该方法只能在这个类体内被访问internal表示该方法可以被同处于一个工程的文件访问static表示该方法属于类型本身,而不属于某特定对象virtual表示该方法可在派生类中重写,来更改该方法的实现abstract表示该方法仅仅定义了方法名及执行方式,但没有给出具体实现,所以包含这种方法的类是抽象类,有待于派生类的实现override表示该方法是将从基类继承的virtual方法的新实现sealed表示这是一个密封方法,它必须同时包含override修饰,以防止它的派生类进一步重写该方法extern表示该方法从外部实现第23页/共79页第二十四页,共79页。方法修饰符中public、protected、private、internal、protected internal属于访问修饰符,表示访问的级别,默认情况下,方法的访问级别为public。访问修饰符的组合表3.3所列的组合被视为非法(fif)的无效组合。 返回类型方法可以返回值也可以不返回值。如果返回值,则需要说明返回值的类型,默认情况下为 void。第24页/共79页第二十五页,共79页。修 饰 符不能与下列选项一起使用staticvirtual、abstract 和 overridevirtualstatic、abstract 和 overrideoverridenew、static 和 virtualabstractvirtual 和 staticnewoverrideexternabstract第25页/共79页第二十六页,共79页。方法名每个方法都有一个名称Main()是为开始执行程序的方法预留的,不要使用C#的关键字作为方法名。方法的命名尽可能地顾名思义。形参表由零个或多个用逗号分隔的形式参数组成,形式参数可用属性、参数修饰符、类型等描述。当形参表为空时,外面的圆括号(kuho)也不能省略。 方法体用花括号(kuho)括起的一个语句块。第26页/共79页第二十七页,共79页。using System;class StackTp int MaxSize; int Top; int StkList; public StackTp ( ) / 构造函数构造函数 MaxSize=100;Top=0;StkList=new int MaxSize; public StackTp(int size)/ 构造函数构造函数 MaxSize=size; Top=0; StkList=new int MaxSize; public bool isEmptyStack() / 方法方法(fngf) if (Top=0) return true; elsereturn false;public bool isFullStack() if (Top=MaxSize)return true; else return false;public void push(int x) StkListTop=x; Top+;【例3.6】 StackTp类定义了几个方法以模拟(mn)实现一个压栈操作。第27页/共79页第二十八页,共79页。 class Test public static void Main() StackTp ST = new StackTp(20); string s1; if ( ST.isEmptyStack() ) / 调用方法调用方法isEmptyStack() s1=Empty; else s1=not Empty; Console.WriteLine (Stack is + s1); for (int i=0; iy) tmp=x; x=y; y=tmp; if (xz) tmp=x; x=z; z=tmp; if (yz) tmp=y; y=z; z=tmp; class Test static void Main() Myclass m = new Myclass ( ); int a, b, c; a=30; b=20; c=10; m.Sort (a, b, c); Console.WriteLine (a=0, b=1, c=2 , a, b, c ); Console.Read (); 【例3.7】 下面的程序演示了当方法Sort传递的是值参数(cnsh)时,对形参的修改不影响其实参。第30页/共79页第三十一页,共79页。 a、b、c 变量的值并没有发生改变,因为它们都是按值传给形参x、y、z的,形参x、y、z的变化并不影响外部a、b、c的值。但如果给方法传递的是一个引用对象时,它遵循的仍是值参数传递方式,形参另外分配一块(y kui)内存,接受实参的引用值副本,同样对引用值的修改不会影响外面的实参。但是,如果改变参数所引用的对象将会影响实参所引用的对象,事实上,它们是同一块(y kui)内存区域。程序运行结果(ji gu)如下:第31页/共79页第三十二页,共79页。using System;class Myclass public void SortArray (int a) int i, j, pos,tmp; for (i=0; ia.Length 1 ; i+) for (pos=j=i; ja j) pos=j; if (pos != i ) tmp=ai; ai=apos; apos=tmp; class Test static void Main() Myclass m = new Myclass ( );int score = 87,89,56,90,100,75,64,45, 80, 84 ; m.SortArray(score); for ( int i=0; iy) tmp=x; x=y; y=tmp; if (xz) tmp=x; x=z; z=tmp; if (yz) tmp=y; y=z; z=tmp; class Teststatic void Main() Myclass m = new Myclass ( );int a, b, c;a=30; b=20; c=10;m.Sort (ref a, ref b, ref c);Console.WriteLine (a=0, b=1, c=2 , a, b, c ); Console.Read();【例3.9】 将例3.7程序(chngx)中Sort方法的值参数传递方式改成引用参数传递,这样在方法Sort中对参数x、y、z按从小到大的排序影响了调用它的实参a、b、c。第34页/共79页第三十五页,共79页。使用ref时请注意:(1)ref关键字仅对跟在它后面的参数有效,而不能应用于整个参数表。(2)在调用方法时,也用ref修饰实参变量,因为是引用参数,所以要求实参与形参的数据类型必须完全匹配,而且(r qi)实参必须是变量,不能是常量或表达式。(3)在方法外,ref参数必须在调用之前明确赋值,在方法内,ref参数被视为已赋过初始值。3. 输出参数在参数前加out修饰符的被称为输出参数,它与ref参数相似,只有一点除外,就是它只能用于从方法中传出值,而不能从方法调用处接受实参数据。在方法内out参数被认为是未赋过值的,所以在方法结束之前应该对out参数赋值。程序运行结果(ji gu)如下:第35页/共79页第三十六页,共79页。using System;class Myclass public void MaxMinArray (int a, out int max, out int min, out double avg ) int sum ; sum = max = min = a0 ;for (int i=1; imax) max=ai; if (aimin) min=ai; sum+=ai;avg=sum / a.Length; class Test static void Main() Myclass m = new Myclass ( );int score = 87,89,56,90,100,75,64,45, 80, 84 ;int smax, smin;double savg;m.MaxMinArray(score, out smax, out smin, out savg);Console.Write (Max=0, Min=1, Avg=2 , smax, smin, savg ); Console.Read ();【例3.10】 求一个(y )数组中元素的最大值、最小值和平均值。第36页/共79页第三十七页,共79页。ref和out参数的使用并不局限于值类型参数,它们(t men)也可用于引用类型来传递对象。程序运行结果(ji gu)如下:第37页/共79页第三十八页,共79页。using System;class Myclass public void Swap1 (string s, string t) string tmp; tmp=s; s=t; t=tmp;public void Swap2 (ref string s, ref string t) string tmp; tmp=s; s=t; t=tmp; class Teststatic void Main() Myclass m = new Myclass ( ); string s1=ABCDEFG, s2=134567; m.Swap1(s1,s2); Console.WriteLine (s1=0 , s1 ); / s1,s2的引用并没有的引用并没有(mi yu)改变改变 Console.WriteLine (s2=0 , s2 ); m.Swap2(ref s1, ref s2); / s1,s2的引用互相交换了的引用互相交换了 Console.WriteLine (s1=0 , s1 ); Console.WriteLine (s2=0 , s2 ); Console.Read ();【例3.11】 下面程序定义了两个方法,一个是Swap1,一个是Swap2,它们都有两个引用对象作为参数,但Swap2的参数加了ref修饰,调用这两个方法产生的结果(ji gu)是不一样的。第38页/共79页第三十九页,共79页。4参数数组一般而言,调用方法时其实参必须与该方法声明的形参在类型和数量上相匹配,但有时候我们更希望灵活一些,C#提供了传递可变长度参数表的机制(jzh),使用params关键字来指定一个可变长的参数表。程序运行结果(ji gu)如下:第39页/共79页第四十页,共79页。using System;class Myclass public void MaxMin (out int max, out int min, params int a ) if (a.Length=0) / 如果可变参数为零个,可以取一个约定值或产生(chnshng)异常max=min=1; return ;max = min = a0 ;for (int i=1; imax) max=ai;if (aimin) min=ai;class Test static void Main() Myclass m = new Myclass ( ); int score = 87,89,56,90,100,75,64,45, 80, 84 ; int smax, smin; m.MaxMin (out smax, out smin); / 可变参数的个数可以是零个 Console.WriteLine (Max=0, Min=1 , smax, smin ); m.MaxMin (out smax, out smin, 45, 76, 89, 90 ); / 在4个数之间找最大、最小 Console.WriteLine (Max=0, Min=1 , smax, smin ); m.MaxMin (out smax, out smin, score); / 可变参数也可接受(jishu)数组对象 Console.WriteLine (Max=0, Min=1 , smax, smin ); Console.Read (); 【例3.12】 下面程序演示了Myclass类中的方法MaxMin有一个参数数组类型的参数,在调用这个(zh ge)方法时具有灵活性。第40页/共79页第四十一页,共79页。using System;class Myclass public void MaxMin (out int max, out int min, params int a ) if (a.Length=0) / 如果可变如果可变参数为零个,可以取一个约定值或产生参数为零个,可以取一个约定值或产生(chnshng)异常异常max=min=1; return ;max = min = a0 ;for (int i=1; imax) max=ai;if (ai=y ? x : y ;public double max (double x, double y) return x=y ? x : y ;public int max (int x, int y, int z) return max ( max (x, y), z) ;public double max ( double x, double y, double z) return max ( max (x, y), z) ; 第44页/共79页第四十五页,共79页。 class Test static void Main() Myclass m = new Myclass ( ); int a, b, c; double e, f, g ; a=10; b=20; c=30; e = 1.5; f = 3.5 ; g = 5.5; / 调用(dioyng)方法时,编译器会根据实参的类型和个数调用(dioyng)不同的方法 Console.WriteLine (max(0,1)= 2 ,a,b, m.max(a,b); Console.WriteLine (max(0,1,2)= 3 ,a,b,c, m.max(a,b,c); Console.WriteLine (max(0,1)= 2 , e,f,m.max(e,f); Console.WriteLine (max(0,1,2)= 3 ,e,f,g, m.max(e,f,g); Console.Read (); 程序运行结果(ji gu)如下: 第45页/共79页第四十六页,共79页。类Myclass中有4个同名的方法max,或参数个数不一样,或参数类型不一样。在调用max方法时,编译器会根据调用时给出的实参个数及类型调用相应(xingyng)的方法,这就是编译时实现的多态。在一个有继承关系的类层次结构中,如果派生类与基类有相同名称或签名的成员,那么在派生类中就隐藏了基类成员,为了警示,编译器会发出一个警告信息。如果派生类是有意隐藏基类成员,可在派生类成员声明中加new修饰符,这样可取消警告信息。第46页/共79页第四十七页,共79页。 using System;class Shape protected double width; protected double height; public Shape( ) width=height=0; public Shape(double x) width=height=x; public Shape(double w, double h ) width=w; height=h; public double area ( ) return width*height; 例3.15基类Shape 派生类Triangle和Trapezia new修饰(xish)了area方法第47页/共79页第四十八页,共79页。class Triangle : Shape / 三角形三角形 public Triangle (double x, double y):base(x,y)new public double area ( ) / 派生类方法派生类方法(fngf)与基类方法与基类方法(fngf)同名,编译时会有警告信息同名,编译时会有警告信息return width*height/2 ; class Trapezia : Shape / 梯形梯形 double width2 ; public Trapezia(double w1, double w2, double h) : base (w1, h) width2=w2; new public double area ( ) / 加加new隐藏基类的隐藏基类的area方法方法(fngf) return (width+width2)*height/2 ; 第48页/共79页第四十九页,共79页。使用关键字new修饰方法,可以在一个继承的结构中隐藏有相同签名的方法。基类对象A被引用(ynyng)到派生类对象B时,它访问的仍是基类的方法。更多的时候,我们期望根据当前所引用(ynyng)的对象来判断调用哪一个方法,这个判断过程是在运行时进行的。另一种更为灵活和有效的手段是,首先将基类的方法(fngf)用关键字virtual修饰为虚方法(fngf),再由派生类用关键字override修饰与基类中虚方法(fngf)有相同签名的方法(fngf),表明是对基类的虚方法(fngf)重载。后者的优势在于它可以在程序运行时再决定调用哪一个方法(fngf),这就是所谓的“运行时多态”,或者称动态绑定。【例3.16】 将例3.15改写,Shape类中的方法(fngf)area用virtual修饰,而派生类Triangle和Trapezia用关键字override修饰area方法(fngf),这样就可以在程序运行时决定调用哪个类的area方法(fngf)。第49页/共79页第五十页,共79页。using System;class Shape protected double width; protected double height; public Shape( ) width=height=0; public Shape(double x) width=height=x; public Shape(double w, double h ) width=w; height=h; public virtual double area ( ) / 基类中用virtual修饰符声明(shngmng)一个虚方法 return width*height; class Triangle: Shape / 三角形第50页/共79页第五十一页,共79页。 public Triangle (double x, double y):base(x,y)public override double area ( ) / 派生类中用派生类中用(zhngyng)override修饰符覆盖基类虚方修饰符覆盖基类虚方法法return width*height/2 ; class Trapezia : Shape / 梯形梯形double width2 ;public Trapezia(double w1, double w2, double h) : base (w1, h)width2=w2; public override double area ( ) / 派生类中用派生类中用(zhngyng)override修饰符覆盖基类虚方修饰符覆盖基类虚方法法 return (width+width2)*height/2 ; class Teststatic void Main() /此处代码同上例,在此省略。此处代码同上例,在此省略。 第51页/共79页第五十二页,共79页。由于area方法在基类被定义为虚方法又在派生类中被覆盖,所以当基类的对象引用A被引用到派生类对象时,调用的就是派生类覆盖的area方法。在类的层次结构中,只有使用override修饰符,派生类中的方法才可以覆盖(重载)基类的虚方法,否则就是隐藏基类的方法 有关虚方法的使用,请注意:(1)不能将虚方法声明为静态的,因为多态性是针对对象的,不是针对类的。(2)不能将虚方法声明为私有的,因为私有方法不能被派生类覆盖。(3)覆盖方法必须与它相关的虚方法匹配,也就是说,它们的方法签名(方法名称(mngchng)、参数个数、参数类型)、返回类型及访问属性等都应该完全一致。(4)一个覆盖方法覆盖的必须是虚方法,第52页/共79页第五十三页,共79页。为了实现良好的数据封装和数据隐藏,类的字段成员的访问属性一般设置成private或protected,这样在类的外部就不能直接读/写这些字段成员了,通常的办法是提供public级的方法来访问私有(syu)的或受保护的字段。但C#提供了属性(property)这个更好的方法,把字段域和访问它们的方法相结合。对类的用户而言,属性值的读/写与字段域语法相同;对编译器来说,属性值的读/写是通过类中封装的特别方法get访问器和set访问器实现的。属性的声明方法如下:语法形式:属性集信息 属性修饰符 类型 成员名 访问器声明第53页/共79页第五十四页,共79页。其中: 属性修饰符与方法修饰符相同,包括new、static、virtual、abstract、override和4种访问修饰符的合法组合,它们遵循相同的规则。 类型(lixng)指定该声明所引入的属性的类型(lixng)。 成员名指定该属性的名称。访问器声明声明属性的访问器,可以是一个get访问器或一个set访问器,或者两个都有。语法形式:get / 读访问器 / 访问器语句块set / 写访问器 / 访问器语句块第54页/共79页第五十五页,共79页。get访问器的返回值类型与属性的类型相同,所以在语句块中的return语句必须(bx)有一个可隐式转换为属性类型的表达式。set访问器没有返回值,但它有一个隐式的值参数,其名称为value,它的类型与属性的类型相同。同时包含get和set访问器的属性是读/写属性,只包含get访问器的属性是只读属性,只包含set访问器的属性是只写属性。【例3.17】 对TextBox类的text、fontname、fontsize、multiline域提供属性方式的读/写访问。第55页/共79页第五十六页,共79页。using System;class TextBoxprivate string text;private string fontname;private int fontsize;private bool multiline;public TextBox ( )text=text1;fontname=宋体;fontsize=12;multiline=false;public string Text / Text属性(shxng),可读可写get return text;set text=value;第56页/共79页第五十七页,共79页。public string FontName / FontName属性(shxng),只读属性(shxng)get return fontname;public int FontSize / FontSize属性(shxng),可读可写get return fontsize;set fontsize = value;public bool MultiLine / MultiLine属性(shxng),只写set multiline = value;第57页/共79页第五十八页,共79页。class Teststatic void Main() TextBox Text1= new TextBox ();/ 调用Text属性(shxng)的get访问器Console.WriteLine (Text1.Text= 0 , Text1.Text); Text1.Text = 这是文本框 ; / 调用Text属性(shxng)的set访问器Console.WriteLine (Text1.Text= 0 , Text1.Text); Console.WriteLine (Text1.Fontname= 0 , Text1.FontName); Text1.FontSize=36;Text1.MultiLine = true;Console.WriteLine (Text1.FontSize= 0 , Text1.FontSize); Console.Read ();第58页/共79页第五十九页,共79页。程序运行结果(ji gu)如下:在这个示例中,类TextBox定义了4个属性,在类体外使用这些属性是用Text1.Text,Text1.FontName等形式,它们和字段域的访问非常类似。编译器根据它们出现的位置调用不同的访问器,如果在表达式中引用(ynyng)该属性则调用get访问器,如果给属性赋值则调用set访问器,赋值号右边的表达式值传给value。属性是字段的自然扩展,当然属性也可作为特殊的方法使用,并不要求它和字段域一一对应,所以属性还可以用于各种控制和计算。【例3.18】 定义(dngy)Label类,设置Width和Heigh属性,分别存放两点之间在水平坐标轴和垂直坐标轴上的投影长度。第59页/共79页第六十页,共79页。 using System;class Point int x, y;public int Xget return x;public int Ygetreturn y;public Point ( ) x=y=0;public Point (int x, int y)this.x=x;this.y=y;第60页/共79页第六十一页,共79页。class Label Point p1=new Point ( );Point p2=new Point (5, 10);public int Width / 计算两点之间在水平(shupng)坐标轴上的投影长度get return p2.Xp1.X;public int Height /计算两点之间在垂直坐标轴上的投影长度get return p2.Yp1.Y;第61页/共79页第六十二页,共79页。class Teststatic void Main() Label Label1= new Label ();Console.WriteLine (Label1.Width= 0 , Label1.Width); /Label1.Width=5Console.WriteLine (Label1.Height= 0 , Label1.Height);/Label2.Height=10Console.Read ();注意:尽管属性与字段域有相同的使用语法,但它本身并不代表字注意:尽管属性与字段域有相同的使用语法,但它本身并不代表字段域。属性不直接对应存储位置,所以不能把它当变量使用,不能段域。属性不直接对应存储位置,所以不能把它当变量使用,不能把属性作为把属性作为ref或者或者out参数传递。属性和方法一样参数传递。属性和方法一样(yyng),也有静,也有静态修饰,在静态属性的访问器中不能访问静态数据也不能引用态修饰,在静态属性的访问器中不能访问静态数据也不能引用this。第62页/共79页第六十三页,共79页。【例3.19】 学生成绩管理程序。根据学生选修的课程及课程学分和课程成绩计算GPA,最后按GPA的值对学生进行排序。基本思路:本程序的学生总人数、课程名、课程学分可以由控制台输入,为叙述简单,假定每个学生所选修的课程相同。Course类定义了课程名、课程学分字段域,并使用属性公开私有字段。另外,Course类还定义了Name属性、构造函数。Course类代码(di m)如下:第63页/共79页第六十四页,共79页。class Coursestring courseName; / 课程(kchng)名 int courseMark; / 课程(kchng)学分public Course() public Course(string Name, int Mark)courseName=Name;courseMark=Mark;public string Name / Name属性,课程(kchng)名可读可写get return courseName;set courseName=value;第64页/共79页第六十五页,共79页。public int Mark / Mark属性,课程学分可读可写get return courseMark;set courseMark=value; Student类定义学生姓名、学号、选修课程数、Course类、成绩及GPA等字段,并使属性公开(public)。假定选修课程一样,所以将课程数、Course类对象定义为static字段,不需要每个学生都有这份数据副本(fbn)。Student类还定义了CourseNum静态属性、GPA属性、Name属性,SetCourse方法,用于设置课程名,因为不需要为每个学生设置,所以定义成静态方法。AddData属性给每个学生加入姓名、学号、成绩。ComputeGPA 方法计算学生成绩的GPA。stuSwap方法对两个Student对象内容进行交换。Student类的代码如下:第65页/共79页第六十六页,共79页。class Studentstring stuName; / 学生姓名string stuID; / 学生学号static int numberOfCourse; / 加static修饰符表明(biomng)这个域为所有学生类对象共享static Course list ; / Course类对象数组,用于设置每门课程名、课程学分int stuScore; / 每个学生对象要填写的各课程成绩double stuGPA; / GPA值public Student() / 当第一次创建Student对象时,创建list对象数组,并初始化list=new CoursenumberOfCourse; for (int i=0; inumberOfCourse;i+)listi=new Course();stuScore=new intnumberOfCourse; / 将CourseNum定义成静态属性是因为它只对静态域进行操作public static int CourseNum 第66页/共79页第六十七页,共79页。get return numberOfCourse;set numberOfCourse=value;public double GPA / GPA属性(shxng)是只读属性(shxng)getreturn stuGPA;public string Name / Name属性(shxng)可读可写get return stuName;setstuName=value;第67页/共79页第六十八页,共79页。/ 将SetCourse设为静态方法(fngf),是因为它仅访问静态数据域/ 不需要创建Student类对象就可直接用Student类名调用/ 它的形参是一个参数数组,这样调用时就可根据实际选修的课程数来设置public static void SetCourse(params Course topic)for (int i=0; itopic.Length ; i+)listi.Name =topici.Name;listi.Mark =topici.Mark; / AddData方法(fngf)将一个学生的数据添加到学生类对象数组中public void AddData(string name,string Id,int score)stuName=name;stuID=Id;for (int i=0;iscore.Length; i+)stuScorei=scorei;第68页/共79页第六十九页,共79页。public void ComputeGPA() / 根据课程的学分以及学生成绩(chngj)计算GPAint i;double sMark, sumMark=0, sumGP=0;for (i=0;i=95) sMark=4.5; else if (stuScorei=90) sMark=4; else if (stuScorei=85) sMark=3.5;第69页/共79页第七十页,共79页。else if (stuScorei=80) sMark=3; else if (stuScorei=75) sMark=2.5; else if (stuScorei=70) sMark=2; else if (stuScorei=65) sMark=1.5; else if (stuScorei=60) sMark=1; else sMark=0;sumGP+=listi.Mark*sMark;sumMark+=listi.Mark;stuGPA=sumGP/sumMark;/ stuSwap方法提供两个Student类对象的交换(jiohun)操作,注意它们的形参被修饰为ref第70页/共79页第七十一页,共79页。public void stuSwap(ref Student stu1, ref Student stu2) string name,Id;int i;int score=new int Student.CourseNum;doub
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!