![第04章面向对象编程技术_第1页](http://file2.renrendoc.com/fileroot_temp3/2021-11/11/20433a9c-a0ee-475f-bfbc-1b1cca396ad0/20433a9c-a0ee-475f-bfbc-1b1cca396ad01.gif)
![第04章面向对象编程技术_第2页](http://file2.renrendoc.com/fileroot_temp3/2021-11/11/20433a9c-a0ee-475f-bfbc-1b1cca396ad0/20433a9c-a0ee-475f-bfbc-1b1cca396ad02.gif)
![第04章面向对象编程技术_第3页](http://file2.renrendoc.com/fileroot_temp3/2021-11/11/20433a9c-a0ee-475f-bfbc-1b1cca396ad0/20433a9c-a0ee-475f-bfbc-1b1cca396ad03.gif)
![第04章面向对象编程技术_第4页](http://file2.renrendoc.com/fileroot_temp3/2021-11/11/20433a9c-a0ee-475f-bfbc-1b1cca396ad0/20433a9c-a0ee-475f-bfbc-1b1cca396ad04.gif)
![第04章面向对象编程技术_第5页](http://file2.renrendoc.com/fileroot_temp3/2021-11/11/20433a9c-a0ee-475f-bfbc-1b1cca396ad0/20433a9c-a0ee-475f-bfbc-1b1cca396ad05.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第4章面向对象编程技术面向对象的程序设计方法是当前程序设计的人势所趋。面向对象的程序设计方法是对结 构化程序设计方法的重新认识。在程序的设计中,方法总是与特定的数据结构密切相关的, 方法含有对数据结构的访问,特定的方法只适用丁特定的数据结构,因此方法与数据结构在 编程中应该是一个密不可分的整体,这个整体叫对彖。c#通过类、对象、继承、多态等机制形成一个完善的而向对象的编程体系。4. 1类和对象类是c#程序设计的基本单位。4.1.1类和对象概述现实生活中的类是人们対客观対象不断认识而产生的抽象的概念,而対象则是现实牛活 小的一个个实体。例如,人们在现实生活小接触了人量的汽车、摩托车、h行车等实体
2、,从 而产牛了交通工具的概念,交通工具就是一个类,而现实牛活中的具体的汽车、摩托车白行 车等则是该类的对象。面向对象程序设计的类从本质上和人们现实生活中的这一认识过程是相同的。例如在编 程实践中,人们经常使用按钮这一控件,每一个具体的按钮是一个按钮对彖,而按钮类则是 按钮对象的抽象,并且人们把这一抽象用计算机编程语言表示为数据集合与方法集合的统一 体,然后再用这个类创建一个个具体的按钮对象。可以把类比作一种蓝图,而对象则是根据蓝图所创建的实例,可以把类比作牛产模具, 而対象则是由这种模具产生的实例(产品)。所以人们乂把对象叫做类的实例。类是対事物的 定义,而对象则是该事物本身。在visual
3、studio.net集成环境屮的,工具箱中的一个个控件,是被图形文字化的可视的 类,而把这些控件添加到窗体设计器中后,窗体设计器中的控件则是对彖,即由工具箱中的 类创建的对象。类是一种数据类型,在c#屮,类这种数据类型可以分为两种:一种是由系统提供的预先 定义的,这些类在.net框架类库中;一种是用户定义数据类型。在创建对象之前必须先定义 该对彖所属的类。然后由类声明对彖。类本质上是一种数据类型,所以类的川法与棊本数据类型的用法基木相同,事实上,在 visual studio.net中像int、float等棊本数据类型也是特殊的类。那么,用棊本数据类型可以 声明变量,用类类型也可以声明变量,只
4、不过类类型的变量叫类的対象或类的实例。4.1.2类定义类定义的格式与结构定义的格式相似,在类定义中需要使用关键字class,其简单的定义 格式为:class类名类体“类名”是一个合法的c#标识符,表示数据类型(类类型)名称,“类体”以一对大括 号开始和结束,在一对大括号后而可以跟一个分号。例如:class student 类名为 studentpublic string id;public string name;public bool sex;上例中,定义了一个名为“student” (学生)的类,类体中包括学生的学号(“id”)、姓 名(“name”)与性别(“sex”)。在上例的“类体”
5、中声明的数据都使用“public”修饰,“public” (公共的)表示这些数 据可以直接进行访问。如果仅从“student”类的定义形式看,其与结构类型除了关键字外几乎没冇任何差别。 当然这只是为了说明问题方便,这种定义方式并不符合面向对象程序设计的原则,因为类中 缺少了对数据的操作。“类体”包括类屮的所有数据及对数据的操作,面向对象程序设计将数据与对数据的操 作作为一个整体,以类的形式进行定义,这种机制叫“封装”。在“类体”中,所冇的数据及对数据的操作的集合叫类成员,类成员的种类很多,本章 仅介绍“字段”、“属性”、“方法”与“构造函数”。“字段”是类定义中的数据,也叫类的变量。在上例中定
6、义的“id”、“name”与“sex” 等均为类中的字段。“属性”用于读取和写入“字段”值,“屈性”是字段的自然扩展,对用户而言,“属性” 等同于“字段”木身,对程序员而言,属性是一种读写“字段”的特殊方法。“方法”实质上就是函数,用于对字段进行计算和操作,即对类中的数据进行操作,以 实现特定的功能。4.1.3声明与使用对象定义类之后,可以用定义的类声明对象,声明对象后可以访问对象成员。每一个类对象 均貝有该类定义中的所有成员,正如每一个整型变量均可以表示同样的数值范围一样。1. 声明对象声明对彖的格式与声明基本数据类型的格式相同:类名对象名;例如:student s1;声明一个学生类对象s1
7、但是,对象声明后,需用“new”关键字进行初始化,这样才能为对象在内存中分配保 存数据的空间。初始化的格式:对象名=new类名();例如:sl=ncw studcnt(); 为s1分配内存空间可以将声明与初始化对象合二为一,例如:student sl=new student();声明对彖并初始化2. 访问对象访问对象实质是访问对象成员,对对象变量成员的访问与结构变量相同,使用运算 符。例如:s1.id 二 t2345"sl.name="张三”;si. sex=true;上面的代码为对彖s1数据成员赋值。可以使用对象变量为另一对象变量整体赋值,例如,“ student s2;
8、s2s1; ”或astudent s2= s1;”。这时,不需要使用new关键字对“s2”初始化。可以使用对象中的某一成员。例如:string sname=sl.name; 将对彖s1的name成员值赋给字符串变量sname4.1.4值类型与引用类型类定义的类型与结构定义的类型虽然相似,但这两种类型却有很大的差别,这涉及到c# 中变量存储方式的问题。从变量的存储方式看,c#屮的变量可以分为值类型变量与引用类型变量。1. 值类型值类型变量直接包含其木身的数据,因此每个值类型变量木身就包含冇赋给它的值。在c#中,内置数据类型除了字符串(string)类型与对象(object)类型外其余均为值类 型
9、。枚举类型与结构类型也是值类型。例如“intx=42;”,整型变量x就是值类型。2. 引用类型与值类型不同,引用类型变量不包含本身的数据,只是存储对数据的引用,数据保存在 内存的其他位置。例如:using system;class classiclass testpublic int a;int x=42,y=x;test tl=new test();t1.a=42;tcstt2=tl;y=100;t2.a=100;)引用类型与值类型在内存中的存储形式如图4-1所示。值类型变量可以使用变暈来赋值,引用类型变呈也可以使用变录来赋值。例如上例屮的 代码:int x=42,y=x;test tl=n
10、ew test();t1.a=42;test t2=t1; 使川对象变量赋值从图中可以看到,用变量“x”为变量“y”赋值,是将“x”所在内存中的值复制给了 “y”;而用变量“t1”为“t2”赋值,则是将“t1”对数据的引用复制给了 “t2”,即两个 对象变呆使用的是同一内存屮的数据,也就是说,用“t1”为“t2”赋值不需要使用new关 键字对对象初始化,也就没冇为对彖“t2”分配存储数据的内存空间。这样,在改变变量值 时,将发生木质差别。例如上例中的代码:y=100;/y的值为100, x的值仍是424.1.5访问控制在上血类定义的例子中,声明类的数据成员(字段)时,均使用public进行修饰
11、,public 叫访问修饰符。声明类中的成员时,使用不同的访问修饰符,表示对类成员的访问权限不同, 或者说访问修饰符确定了在什么范围可以访问类成员。c#中敲常用的访问修饰符及其意义,如表41所示。表41访问修饰符访问修饰符意义public (公有)访问不受限制,可以被任何其他类访问private (私有访问只限于含该成员的类,即只有该类的其他成员能访问protected (保护)访问只限于含该成员的类、及该类的派生类在类定义中,如果声明成员没冇使用任何访问修饰符,则该成员被认为是私冇(private)的。如果不涉及继承,private少protected没有什么区别。在类定义中,如果成员被声明
12、为private或protected,则不允许在类定义外使用点运算符 访问,即在类定义外,点运算符只能访问public成员。例如在下面的类定义中:class student/类名为 studentiprivate string id; 私有public string name; 公冇 protected bool sex; /保护)student s1 =ncw studcnt();s1.id=12345;非法,id 为 privatesl.name="张三"; 合法,name 为 public sl.scx=truc;非法,sex 为 protected在类定义外使用点运
13、算符访问“id”与“sex”是非法的,而访问“name”则是合法的, 因为 “id” 与 “sex” 是 private 或 protected 的,而"name” 则是 public 的。通常,在类定义中,数据成员(字段)被声明为private或protected,从而实现所谓的数 据隐藏,以确保不能在类外随意访问类的数据成员;而其他种类的成员则被声明为public, 以通过这些成员实现对类的数据成员的访问。4.2属性对私有或保护数据成员常见的访问是读取耳设置修改数据值,在类定义外部,这种访问 可通过加性成员实现。通过属性可以控制对数据的访问方式,甚至设置数据可接受的值域。4.2.
14、1芦明属性在类定义屮声明局性的格式为:访问修饰符类型属性名 可以将属性声明为读写m性、只读属性或只写丿瓜性。1.声明读写属性修改student类定义添加属性声明:class student 类名为 student声明字段private string id;private string name;private bool sex;声明属性public string idgetreturn id;)setid=valuc;1public string namegetreturn name;setname=value;)1public bool sexgetreturn sex;sex=value;
15、在属性声明中,get与set叫属性访问器。get完成对数据值的读取,return川于返回读取 的值;set完成对数据值的设置修改,value是一个关键字,表示要写入数据成员的值。属性名应和其要访问的数据成员名和关但不相同,可以采取数据成员名全用小写,而属 性名的单词首字母人写的方式,如数据成员名为name,则对应的局性名为name。2.声明只读或只写属性在属性声明中,如果只冇get访问器,则该属性为只读属性。例如:public bool sexgetreturn sex;)只读属性意味着,数据成员的值是不能被修改的。在属性芦明中如果只有set访问器,则该属性为只写属性。只写属性在程序设计中不常
16、 使用。421使用属性属性成员的使用就如同公有数据成员的使用一样。可以为可写的属性赋值,可以用可读 的属性为其他变量赋值。以student类为例:student s1 =new student();用属性设宣修改数据成员值s1.id= 12345;si.name 二”张三“;sl.sex=true;用属性读取数据成员值为其他变量赋值bool ssex=sl. sex;如果属性为只读的,则属性不能出现在赋值运算符的左边。在c#程序设计屮,窗体与控件的属性就是这类成员,其屮在属性窗口显示的属性,均为 可读写属性,窗体与控件的只读属性只能在代码中使用。4.3方法方法是把一些相关的语句组织在一起,用于
17、解决某一特定问题的语句块。方法必须放在 类定义中。方法同样遵循先声明后使用的规则。4.3.1声明与调用方法方法的使用分声明与调用两个环节。1.声明方法声明方法最常用的格式:访问修饰符返回类型方法名(参数列表)方法的访问修饰符通常是public,以保证在类定义外部能够调用该方法。方法的返回类型用于指定由该方法计算和返回的值的类型,可以是任何值类型或引用类 型数据,如,int、string及前面定义的student类。如果方法不返回一个值,则它的返回类型 为 voido方法名是一个合法的c#标识符。参数列表在一对圆括号小,指定调用该方法时需要使用的参数个数、各个参数的类型, 参数z间以逗号分隔。参
18、数可以是任何类型的变量。如果方法在调用时不需要参数,则不用 指定参数,但圆括号不能省。实现特定功能的语句块放在一对大括号中,叫方法体,“”表示方法体的开始,“”表 示方法体的结束。如果方法有返回值,则方法体中必须包含一个return语句,以指定返回值,该值对以是 变量、常量、表达式,其类型必须和方法的返回类型相同。如果方法无返回值,在方法体屮 可以不包含return语句,或包含一个不指定任何值的return语句。例如下面的方法声明:public int intmax(int a,int b)int c;if(a>b)c=a;elsec=b;return c;)该方法的功能是求两个整数中较
19、大的整数,并将该整数返冋。该方法的返冋类型是一个 整型值,方法名称为“intmax”,参数列表中有两个整型变量参数“a”少“b”,方法体屮有 一个似uo1语句,该语句指定的返回值是一个整型变量c。该方法体中的语句块也可以用条 件表达式合并为一句:“return a>b?a:b;”。这时,return指定的返冋值是一个条件表达式,return 语句把该表达式运算的结果返回。2.调用方法从方法被调川的位置,可以分为在方法声明的类定义中调用该方法和在方法声明的类定 义外部调用方法。在方法声明的类定义屮调用该方法的格式为:方法名(参数列表)在方法声明的类定义屮调用该方法,实际上是由类定义内部的其
20、他方法成员调用该方法。 例如在类定义内部调用求较大整数函数:class classmaxpublic int getmax(int a,int b)/其他方法成员return inlmax(a,b);在类定义 classmax 内部调用方法 inimax)public int intmax(int a,int b)求较人整数函数return a>b?a:b;)在方法声明的类定义外部调用该方法实际上是通过类声明的对彖调用该方法,其格式为: 对象名方法名(参数列表)【例4-1】创建一个控制台应用程序,并创建一个类,该类仅包含求两个数屮较人数的 方法成员,在main方法中调用该方法。using
21、 system;class classiclass classmax 定义一个类public int lntmax(int a, int b)return a>b?a:b;11static void main(string args)int x=42,y;y=100;classmax classmax二new classmax();声明一个对彖int c二classmax.intmax(x,y);调用对象方法console.wnte(n较大的值为:j;console. writeline(c);consolc.rcadlinc();程序运行的结果为:较大的值为:1004.3.2参数传递在
22、方法的声明与调用中,经常涉及方法参数,在方法声明中使用的参数叫形式参数(形 参),在调用方法中使用的参数叫实际参数(实参)。在调用方法时,参数传递就是将实参传 递给形参的过程。以【例41】为例,声明方法时的形参如下:public int intmax(int aunt b)调用方法时的实参如下:classmax.intmax(x,y)这样就完成了形参与实参的结合,英传递关系如图4-3所示。方法调用:classmax.lntmax(x,y)ii方法声明:public int intmax(int a, int b)图4-3形参与实参方法参数传递按性质可分为按值传递与按引用传递。1.按值传递参数按
23、值的方式传递是指当把实参传递给形参时,是把实参的值复制(拷贝)给形参, 实参和形参使用的是两个不同内存屮的值,所以这种参数传递方式的特点是形参的值发牛改 变时,不会影响实参的值,从而保证了实参数据的安全。按值传递如图4-4所示。实参传递形参图4-4按值传递示意基木类型的参数在传递时默认为按值传递。2.按引用传递方法只能返回一个值,但实际应用中常常甜要方法能够修改或返回多个值,这时只靠 return语句显然是无能为力的。如果需要方法返回多个值,使用按引用传递参数的方式可以 实现这种效果。按引用传递是指实参传递给形参时,不是将实参的值复制给形参,而是将实参的引用传 递给形参,实参与形使用的是一个内
24、存屮的值。这种参数传递方式的特点是形参的值发牛改变时,同时也改变实参的值。实参图46类对象按引丿ij传递示意传递形参按引用传递分基木数据类型与类对彖数据类型两种情况,其传递如图45与图46所示。图4-5基本类型按引川传递示惫基木类型参数按引用传递时,形参实际上是实参的别名。基木类型参数按引用传递时, 实参与形参前均须使用关键字refo【例42】编写一个控制台应用程序,在程序中添加一个交换两个整型变量值的方法。 调用该方法将两个整型变量的值进行交换并输出交换前后的结果。using system; namespace数值交换 class classipublic void swap(ref int
25、 a,ref int b) 形参 a. b 为引用类型 数值交换int c=a;a=b;static void main(stringj args)int a=60,b=80;console.writeline(m交换前 a、b 的值:0), 1”,a,b);classi c=new class 1();c.swap(ref a,refb);以引用方式传递实参a、bconsole.writeline(m交换后 a、b 的值:0), 1”,a,b);console.readline();程序运行结果:交换前a、b的值:60, 80交换后a、b的值:80, 60 因为在swap方法小,对引用形参a
26、、b的值的修改,就是对实参a、b的值的修改,所 以方法swap成功地完成了对a、b数据的交换功能,相当于返回了两个值,这在按值传递的方式下是无法实现的。类对象参数总是按引川传递的,所以类对彖参数传递不需要使川ref关键字。类对彖参 数的传递,实际上是将实参对数据的引用复制给了形参,所以形参与实参共同指向同一个内 存区域。【例4-3】编写一个控制台应用程序,该程序项目名称为“类对象参数”,程序中有两个 类定义,一个是创建程序吋系统口动创建的类class 1,一个是用户口定义的student类。在class 1 类中声明一个方法,该方法以student类对象为参数。在class 1类中的main方
27、法中调用该方 法。using system;namespace类对彖参数class student/类名为 student声明字段private string id;private string name;private bool sex;声明属性 public string id igetreturn id;)setiid=valuc;public string namegetreturn name;setname=value;)public bool sexreturn sex;setsex=value;class classipublic void studentfl(student s
28、ti)以对象 sti 为形参修改形参数据成员的值st1id="56789”;stl.name=”张三”;stl.sex=true;static void main(string args)string ssex;student si; 声明一个学生类对象sis1 =new student(); 为s1分配内存空间s1.id=" 12345"si.name 二"李平";sl.sex=false;if (s1 .sex=true)ssex="男“;elsessex="女";console.writeline(h 学生学
29、号:”+s1 .id+" 姓名:”+s1 .name +”性别:”+ssex); 输出对象si的值classi c=new class 1(); 声明对彖 c 以调用方法 studentfl c.sludentfl(sl);以对象si为实参调用方法if (sl.sex=true)ssex="男";elsessex="女”;console.writeline(m 学生学号:”+s 1.id+" 姓名:”+s l.name +"性别:”+ssex); 输出对象s1的值console.readline();程序运行结果:学生学号:12345
30、姓名:李平性别:女学生学号:56789姓名:张三性别:男结果的笫一行为调用方法前对象s1的值,结果的第二行为调用方法后对彖s1的值。虽 然在main方法中并未对对彖s1进行修改,但由于调用方法studentfl时,将s1传递给了 st1,而类对象参数是按引用传递的,所以在方法studentfl中对st1的修改,就是对s1的 修改,因此,结果的第二行,s1的值发生了变化。4.3.3重载方法有时候方法实现的功能需要针对多种类型的数据,虽然c#有隐式转换功能,但这种转换 在有些悄况下会导致运算结果的错谋,而有时数据类型无法实现隐式转换共至根木无法转换。 例如:using system;class c
31、lassi(public void swap(rcf int a,ref int b)int c=a;a=b;b=c;static void main(string args)int a=60,b=80;consoie-writelinec"交换前 a、b 的值:(), 1“,a,b);classi c=new classic );c.swap(ref a,ref b);调用交换值方法consoie-writelinec"交换后 a、b 的值:(), 1“,a,b);console.rea(jline();上例中的交换方法只能实现两个整型变量的值交换,无法通过隐式或显式转换
32、來实现其 他类型变量的值交换。例如在上例的主方法中添加如下代码:float fa=5.2f,fb=6.0f;c.swap(ref fa,ref fb);运行程序时,将出现“无法从'reffloat'转换为'refint'”的编译错误。为了能使同一功能适用于各种类型的数据,c#提供了方法重载机制。方法重载是声明两个以上的同名方法,实现对不同数据类型的相同处理。方法重载有两点耍求:(1) 重载的方法名称必须相同;(2) 重载的方法,其形参个数或类型必须不同,否则将出现“已经定义了一个具有相同 类型参数的方法成员”的编译错误。如果要使上例中的交换方法能同时处理整型与浮
33、点型数据,重载的方法声明如下:public void swap(rcf int ajcf int b)public void swap(rcf float a,ref float b)声明了重载方法后,当调用具有重载的方法时,系统会根据参数的类型或个数寻求最匹 配的方法予以调用。根据前述的例子,当执行uc.swap(refa,refb);"调用时,系统会调用"public void swap(ref int a,ref int b) ”方法,当执行uc.swap(ref fa,ref fb);”调用时,系统会调用apublic void swap(ref float a,r
34、ef float b) ”方法,从ij实现对不同的数据类型进行相同处理。【例4-4】创建一个控制台应用程序,在该程序中实现对两个整型、浮点型、双精度型、 十进制型与字符型数据比较大小的功能。using system;namespace方法匝载_比较值的大小class classi/比较值大小的方法声明public int max(int a, int b)return a>b?a:b;public float max(float a, goat b)return a>b?a:b;public double max(double a, double b)return a>b?a
35、:b;public decimal max(decimal a, decimal b)return a>b?a:b;public char max(char a, char b)return a>b?a:b;static void main(string args)int ia=60,ib=80;float fa=5.2f,fb=8.8f;double da=6.2,db=7.2;decimal ma=8.2m,mb=9.8m;char ca 二'a',cb 二'b'classi c=ncw classi();console.writeline(mi
36、a 与 ib 较大的值为:0”,c.max(ia,ib); console.writeline(hfa 与 fb 较大的值为:0”,c.max(fa,fb); consolc.writclinc("da 与 db 较大的值为:0",c.max(da,db»console.writeline("ma 与 mb 较大的值为:0",c.max(ma,mb); console.writelinec'ca 与 cb 较大的值为:0“,c.max(ca,cb); console.rcadlinc();程序运行结果为:ia与ib较大的值为:80fa与
37、fb较大的值为:8.8da与db较大的值为:7.2ma与mb较大的值为:9.8ca与cb较人的值为:b在上面的程序例题中,由于float类型可以隐式转换为double类型,因此比较float类型 的值人小的方法可以省略。int类型可以实现隐式转换,但由于int类型既可以隐式转换为 double类型,也可以隐式转换为decimal类型,所以,比较int类型值大小的方法不能省略, 以免产生调用的二义性。4.4构造函数构造函数是一种特殊的方法成员,构造函数的主要作用是在创建对象(声明对象)时初 始化对象。一个类定义必须有至少一个构造函数,如果定义类时,没有声明构造函数,系统 会提供一个默认的构造函数
38、,如果声明了构造函数,系统将不再提供构默认造函数。如果只冇默认构造函数,在创建对彖时,系统将不同类型的数据成员初始化为相应的默 认值,如,数值类型被初始化为0,字符类型被初始化为空格,字符串类型被初始化为null (空值),逻辑(bool)类空被初始化为false等。例如下面的程序:using system;class student/类名为 student声明字段 public string id;public string name; public bool sex;public int age;class classistatic void main(string args)char s
39、sex;studcnt s1 =ncw studcnt();if (s1 .sex=true)ssexj男:elsessex=女;console.writeline("学号:”+sl.id+”姓名:*,+s+”性别:”+sscx+”年龄:0)h,sl.age);console.readline();程序运行的结果为:学号:姓名:性别:女年龄:()这是因为系统将student类的数据成员id与name初始化为null,将sex初始为false,将 age初始为0的缘故。如果想在创建对象吋,将对象的数据成员初始为指定的值,则需要专门声明构造函数。4.4.1声明构造函数声明构造
40、函数与声明普通方法相比,有两个特别要求,一是构造函数不允许有返回类型 包括void类型,二是构造函数的名称必须与类名相同。由于通常声明构造函数是为了在创建对象时,对数据成员初始化,所以构造函数往往需 耍使用形参,例如参考前而的学生(student)类,创建一个学生类对彖时,需耍给出学生的 学号、姓名、性别及年龄等,所以学生类构造函数可以声明如下:public student(string id,string name,bool sex,int age)id=id;name=nam esex=sex; age=age;)rti于声明了上述带参数的构造函数,所以系统不再提供默认构造函数,这样在创建
41、对象 时,必须按照声明的构造函数的参数要求给出实际参数,否则将产生编译错误,例如:student s2=new student(,12345,h张三蔦true,21);由上述创建对象的语句可知,new关键字后面实际是对构造函数的调用。如果声明构造函数时使川的参数名称与类数据成员名称相同,则构造函数中使川的类数 据成员名称需要用关键字this引导,以免系统分不清形参与数据成员而产牛二义性。将上例 屮的形参名称改为与数据成员同名的构造函数声明如下:public student(string id,string name,bool sex,int age)ithis.id=id;=
42、name;this.sex=sex; this.age=age;)关键字this指所创建的对象,是声明对象时,由系统h动传递给构造函数的对象的引用 形参。事实上在调用类的非静态方法成员吋,系统均会口动传递该引用形参,不过最好的办 法是使形参的名称与数据成员的名称有所区别。4.4.2重载构造函数构造函数与方法一样可以重载,重载构造函数的主耍h的是为了给创建对彖提供更大的 灵活性,以满足创建对彖时的不同需耍。例如,在创建一个学生(student)对彖时,有时可 能需要只初始化姓名,而不初始化其他值,那么可以在丽述声明构造函数的基础上再重载一 个只初始化姓名的构造函数,代码如下:public stu
43、dent(string name)name=name;山于该构造函数与前述构造函数的参数个数不同,所以是一个合法的构造函数重载。有 了这个构造函数后,就可以声明只有一个实参的对象,例如:student s3=new student("李平”);如果在声明了带参数的构造函数后,还想保留默认构造函数,则必须显式声明一个默认 构造函数,显式声明的默认构造函数实际上是一个不实现任何功能的空函数。以student类为 例,声明默认构造函数如下:public student()显式声明默认构造函数【例45】根据本节介绍内容,在控制台应用程序中创建student类,并声明构造函数及 构造函数的垂载
44、。using system;namespace构造函数class student类名为 student声明字段public string id;public string name;public char sexx;public bool sex;public int age;/声明构造函数public studcnt()显式声明默认构造函数public student(string id,string name,bool sex,int age)重载初始化学号、姓名、性别与年龄的构造函数this.id=id;=name;this.sex=sex;this.agc=agc;p
45、ublic student(string name)重载只初始化姓名的构造函数name=name;)class classistatic void main(string args)char ssex;声明无参对彖(调用默认构造函数)student s1 =nevv student();if (s1 .sex=true)ssex='男:elsessex 二,女:console.writeline(”学号:”+sl.id+”,姓名:”+sl.namc+”,性别:”+ssex+“,年龄:0",sl.age);/声明带学号、姓名、性别及年龄初始值的对象(调用四参数构造函数) stu
46、dent s2=ncw studcnt(" 12345","张三",truc,21);if (s2.sex=true)sscx 二,男:elsessex=女:console.writeline(“学号:”+s2.id+”,姓名:”+s2.name+”,性别:”+ssex+“,年龄:0",s2.age);声明带姓名初始值的对象(调用一参数构造函数)student s3=new student("李平”);if (s3.sex=true)ssex二'男';elsessex=女;console.writelinec1 学号:
47、”+s3.id+",姓名:”+s3.name+”,性别:”+sscx+",年龄:0)",s3.age);console.rcadlinc();程序运行结果:学号:,姓名:,性别:女,年龄:()学号:12345,姓名:张三,性别:男,年龄:21学号:,姓名:李平,性别:女,年龄:()山于构造函数的重载,程序中可以用不同的初始化方式声明対象,为创建对象提供了灵 活性。4. 5静态成员类可以具冇静态成员,例如静态字段、静态方法等。4.5.1静态数据成员与方法成员静态成员与非静态成员的不同在于,静态成员属于类,阳非静态成员则总是与特定的实 例(对彖)相联系。声明静态成员需
48、要使川static修饰符。1.静态数据成员非静态的字段(数据)总是属于某个特定的对象,其值总是表示某个对象的值。例如, 当说到学号(id)吋,总是指某个学生的学号,而不町能是全体学生的学号,相应的,在前 面定义的student类的id成员就是一个非静态的数据成员。有吋可能会需要类中有一个数据成员来表示全体对彖的共同特征,例如在student类用一 个数据成员来统计学生的人数,那么这个数据成员表示的就不是某个学生对象的特征,而是 全体学牛对象的特征,这时就需要使用静态数据成员。例如:class student类名为 studentpublic static int studentnumber;声
49、明静态数据成员public string id;public string name;public char sexx;public bool sex;public int age;静态数据成员studentnumber不属于任何一个特定的对彖,而是属于类,或者说属于全体 对彖,是被全体对象共享的数据。2.静态方法非静态的方法包括非静态的构造函数总是对某个对象进行数据操作,例如,比较值的大 小方法,总是某个对象的比较值人小的方法,相应的,在前述的例子小类classi中max方法 成员就是一个非静态的方法成员。如果某个方法使用时并不盂要与具体的对象相联系,例如方法操作的数据并不是某个具 体对象的
50、数据而是表示全体对象特征的数据,甚至方法操作的数据与对象数据根木无关,这 时可以将该方法声明为静态方法。例如耍操作前述student类例子中的静态数据成员 studentnumber,则应该声明一个静态方法。静态方法同样使用修饰符static声明,静态方法属于类,只能使用类调川,不能使用对 彖调用。【例4-6创建一个控制台应用程序,在该程序屮定义一个学生类,该类除包含非静态 成员外,还包含一个静态数据成员用以统计学生人数(对象个数),一个静态方法用以返冋学 生人数。using system;nanicspacc静态成员class student 类名为 student声明字段public st
51、atic int studentnumber;声明都态数据成员public string id;public string name;public char sexx;public bool sex;public int age;public student(string id,string name,bool sex,int age)/声明构造函数studentnumber+;/每创建一个对彖,i浄态数据成员增1this.id=id;this.na me二name:this.sex=sex; this.age=age;1public static int getnumber()声明静态方法r
52、eturn studentnumber;static void main(string args)char ssex;student s1 =ncw student(” 12345",”张三“,true,21);声明对象 si讦(s1 .sex 二二true)ssex=男:elsessex=女;console.writeline("学号:”+sl.id+”,姓名:"+s+”,性别:”+sscx+",年龄:0”,si.age);student s2=new student(”23456”,”李四",false,20);声明对象 s2i
53、f (s2.sex=true)ssex='男'elsessex='a';consoie.writeline("学号:”+s2.id+",姓名:h+s2.name+”,性别:”+ssex+“,年龄:0”,s2.age);student s3=new student("34567","王五",true,19);/声明对象 s3if (s3.sex=true)ssex男elsessex=女:console.writeline(“学号:”+s3.id+”,姓名:”+s3.name+”,性别:”+ssex+”,年
54、龄:0)",s3.age);console.writeline("学生人数为:0)",student.getnumber();/调用静态方法console.readline();程序运行结果:学号:12345,学号:23456,学号:34567,学生人数为:3姓名: 姓名: 姓名:张三, 李四, 王五,性别:性别:性别:男,年龄: 女,年龄: 男,年龄:212019该程序在构造函数被调川时,使静态数据成员studentnumber自动增1,从而起到自动统计学生人数的作用,程序屮的静态方法在调用时,是由类student h接调用的,如果用对象调用则是非法的。静态方法
55、非静态方法一样可以重载。【例4-7】修改【例4-4】,将比较值人小的方法重载声明为静态方法并在main方法小调 用这些方法。using system;namespace静态方法重载class classi比较值大小的重载静态方法声明public static int max(int a, int b)return a>b?a:b;public static float max(float a, float b)return a>b?a:b;public static double max(double a, double b)return a>b?a:b;public static decimal max(decimal a, decimal b)return a>b?a:b;public static char max(char a, char b)return a>b?a:b;static void main(string args)int ia=60,ib=80;noat fa=5.2f,l*b=8.8f;double da=6.2,db=7.2;decimal ma=8.2m,mb=9.8m;char ca=a',cb='b'调用重载静态方法console
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 二零二五年度长沙新环境房屋租赁与节能改造合同
- 2025年度办公室助理实习生实习期间权益保护合同
- 家具买卖合同
- 农业生产质量管理体系建设作业指导书
- 房屋买卖合同委托书
- 合伙人合作协议合同
- 企业危机管理作业指导书
- 第三方代付款协议书
- 三农村环境保护与管理方案
- 建筑垃圾买卖合同
- 电网工程设备材料信息参考价(2024年第四季度)
- 2025年江苏农牧科技职业学院高职单招职业技能测试近5年常考版参考题库含答案解析
- 2025江苏连云港市赣榆城市建设发展集团限公司招聘工作人员15人高频重点提升(共500题)附带答案详解
- 2025年全年日历-含农历、国家法定假日-带周数竖版
- 《东北大学宣传》课件
- 社会主义从空想到科学的发展
- 《轨道交通工程盾构施工技术》 课件 项目2 盾构构造认知
- 《传统发酵馒头酸菜》课件
- 《港珠澳大桥演讲》课件
- 《有机化学》课件-第十章 羧酸及其衍生物
- 人教版道德与法治五年级下册《第一单元 我们一家人》大单元整体教学设计2022课标
评论
0/150
提交评论