版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第5章 面向对象程序设计基础,2010-11-19,面向对象的软件开发技术是当今计算机技术发展的重要成果和趋势之一。 C#是完全面向对象的程序设计语言。 类和对象是面向对象程序设计中的重要概念。 封装性、继承性和多态性是面向对象的特点。 本章主要介绍面向对象程序设计中的基本概念和基于C#的面向对象程序设计的方法。,2020/7/14,2,C#程序设计实用教程,基本概念,5.1 面向对象概述,5.1.1 面向对象的概念 面向对象程序设计(Object-Oriented Programming)简称OOP技术。 面向对象编程技术是计算机编程技术中一次重大的进步。 在面向对象编程技术出现之前,程序的
2、设计普遍采用的是面向过程的程序设计方法。,2020/7/14,3,C#程序设计实用教程,5.1.1 面向对象的概念 OOP是一种系统化的程序设计方法,强调直接以问题域(即现实世界)中的事物为中心来考虑问题,并按照这些事物的本质特征把它们抽象为对象。 OOP的主要思想是将数据及处理这些数据的操作都封装(Encapsulation)到一个称为类(Class)的数据结构中。使用这个类时,只需要定义一个类的变量即可,这个变量(Object)。通过调用对象的数据成员完成对类的使用。 在这种方法下,编程人员不需要过分关注“如何做”,而是重点关注“做什么”。OOP编程思想较好地适应了现实世界中的问题,因而得
3、以广泛应用。,2020/7/14,4,C#程序设计实用教程,5.1.2 面向对象语言的特点,面向对象的编程方式具有继承、封装和多态性等特点。 (1)继承 在生活中,事物有很多的相似性,这种相似性是人们理解纷繁事物的一个基础。因为事物之间往往具有某种“继承”关系。 比如,儿子和父亲往往有许多相似之处,因为儿子从父亲那里遗传了许多特性;,2020/7/14,5,C#程序设计实用教程,5.1.2 面向对象语言的特点,继承(inheritance)是面向对象编程技术的一块基石,通过它可以创建分等级层次关系的类。 继承是父类和子类之间共享数据和方法的机制,通常把父类称为基类,子类称为派生类。子类可以从其
4、父类中继承属性和方法,通过这种关系模型可以简化类的设计。 。,2020/7/14,6,C#程序设计实用教程,5.1.2 面向对象语言的特点,例如,可以将水果看作一个父类,那么水果类具有颜色属性。然后再定义一个香蕉类,在定义香蕉类时就不需要定义香蕉类的颜色属性,通过如下继承关系可以使香蕉类具有颜色属性。 class 水果类 Public 颜色;/在水果类中定义颜色属性 class 香蕉类 : 水果类 /香蕉类中其他的属性和方法 ,2020/7/14,7,C#程序设计实用教程,5.1.2 面向对象语言的特点,(2) 封装 类是属性和方法的集合,为了实现某项功能而定义类后,开发人员并不需要了解类体内
5、每行代码的具体涵义,只需通过对象来调用类内某个属性或方法即可实现某项功能,这就是类的封装。 封装提供了外界与对象进行交互的控制机制,设计和实施者可以公开外界需要直接操作的属性和方法,而把其他的属性和方法隐藏在对象内部。这样可以让软件程序封装化,而且可以避免外界错误地使用属性和方法。,2020/7/14,8,C#程序设计实用教程,5.1.2 面向对象语言的特点,(3) 多态性 类的多态(polymorph)指对于属于同一个类的对象,在不同的场合能够表现出不同的特征。 多态性主要指在一般类中定义的属性或行为,被特殊类继承之后,可以具有不同数据类型或表现出不同的行为。这使得同一个属性或行为在一般类及
6、其各个特殊类具有不同的意义。 例如:某个对象,其基类为“笔”,在调用它的“写”方法时,程序会自动判断出它的具体类型,如果是毛笔,则调用毛类对应的“写”方法,如果是铅笔,则调用铅笔对应的“写”方法。,2020/7/14,9,C#程序设计实用教程,5.2定义类,在C#中,“类”是一种数据结构,它可以包含数据成员(常量和字段)、函数成员(方法、属性、事件、索引器、运算符、构造函数、析构函数)。 类是个静态的概念,如果要使用某个类,就应该定义该类的一个或多个实例,每一个实例就是一个对象。,2020/7/14,10,C#程序设计实用教程,5.2.1 类的概念,类是对象概念在面向对象编程语言中的反映,是相
7、同对象的集合。类描述了一系列在概念上有相同含义的对象,并为这些对象统一定义了属性和方法。 类是对象的抽象描述和概括。例如:汽车是一个类,只要是汽车都有车牌,颜色,车轮、车门、发动机等特性,都可以 加速,刹车,转方向等行为。这是将所有的汽车进行归纳之后得出的共有的特性,但这些特性都是抽象的,非常不具体,只是用来描述一个类别,并不能具体指一辆汽车。 而具体到某辆汽车就是一个对象了,例如:车牌照为苏A2345*的黑色奥迪轿车,这就是汽车类的一个汽车对象。用具体的属性可以在汽车类中唯一确定自己,并且对象具有类的操作,2020/7/14,11,C#程序设计实用教程,5.2.1 类的概念,在C#中,所有的
8、内容都被封装在类中,类是C#的基础,每个类通过属性和方法及其他一些成员来表达事物的状态和行为。 事实上,编写C#程序的主要任务就是定义各种类及类的各种成员。,2020/7/14,12,C#程序设计实用教程,5.2.2 类的声明,简单地讲,类是一种数据结构,用于模拟现实中存在的对象和关系,包含静态的属性和动态的方法。 下面来看如何声明类及其属性、方法。在声明一个类之前,需要向工程中新添加一个文件。,2020/7/14,13,C#程序设计实用教程,5.2.2 类的声明,1. 向工程添加新项目 在VS.NET中添加一个新的类文件以及其他新项目。操作很简单,具体步骤如下: (1)在【解决方案浏览器】视
9、图中,在工程上单击右键,再在打开的快捷菜单中选择【添加】【类】,如图5-1所示。,2020/7/14,14,C#程序设计实用教程,5.2.2 类的声明,(2)在此时弹出的对话框中选择添加类文件,并为新文件命名,以.cs作为后缀,如图5-2所示。 (3)单击【打开】按钮后,就可以在【解决方案浏览器】视图中看到这个新的类文件了。 (4)双击该类文件,可以在其中声明新的类。 当然,也可以把多个功能类似的类放在一个类文件中。,2020/7/14,15,C#程序设计实用教程,5.2.2 类的声明,2. 声明类 C#中类的声明需要使用class关键字,并把类的主体放在花括号中,格式如下: 类修饰符 cla
10、ss 类名 :基类类名 /属性 /方法 其中,除了class关键字和类名外,剩余的都是可选项;类名必须是合法的C#标识符,它将作为新定义的类的类型标识符。,2020/7/14,16,C#程序设计实用教程,5.2.2 类的声明,注意: class关键字前面是访问级别。在C#中,类的访问级别由类的修饰符进行限定,类的修饰符如表5-1所示。在上例中,如果类的修饰符为public,这表示该类可以被任何其他类访问。类的名称位于class关键字的后面。,2020/7/14,17,C#程序设计实用教程,5.2.2 类的声明,以上的类修饰符可以两个或多个组合起来使用,但需要注意下面几点: (1) 在一个类声明
11、中,同一类修饰符不能多次出现,否则会出错。 。,2020/7/14,18,C#程序设计实用教程,5.2.2 类的声明,(2) 在使用public、protected、internal和private这些类修饰符时,要注意这些类修饰符不仅表示所定义类的访问特性,而且还表明类中成员声明中的访问特性,并且它们的可用性也会对派生类造成影响。 (3) 如果省略类修饰符,则默认为私有修饰符private。 (4) 对于具有继承关系的类才有基类。如果一个类没有从任何类继承,就不需要基类类名选项。在C#中,一个类只能从另一个类中继承。,2020/7/14,19,C#程序设计实用教程,5.2.2 类的声明,下面
12、以一个学生类的实例,说明该类在C#中的实现。该类的类图如图5-3所示。 【例5-1】定义一个学生类。 public class Student /属性 /学号、姓名、年龄等 /方法 /长大、入学、毕业等 ,2020/7/14,20,C#程序设计实用教程,5.2.3 类的静态特性,属性(或字段)可以看作是类的静态描述,同样,在定义属性时,也可以使用访问修饰符来定义其访问级别。属性的定义格式如下: 修饰符 数据类型 属性名; 其中,属性修饰符attribe-modifier包括public、private、protected。下面的例子用来说明public和private修饰符的作用。,2020/
13、7/14,21,C#程序设计实用教程,5.2.3 类的静态特性,2020/7/14,22,C#程序设计实用教程,【例5-2】public和private修饰符的作用。 using System; namespace Example_PublicAndPrivate / 学生类 public class Student /属性 public string strName;/公有属性 private int nAge;/私有属性 /方法. ,/ Main函数类 class Test / 应用程序的主入口点。 static void Main(string args) Student s = new
14、 Student(); s.strName = 张三“;/正确 s.nAge = 20;/错误,不能访问 ,5.2.3 类的静态特性,上述程序中,定义一个Student类,包含一个公有属性“strName”和一个私有属性“nAge”。在Test类中,试图对学生类的对象s的年龄进行设置,但是Student类的nAge属性是私有的,在其他的类中无法访问,因此程序会报错,报错信息如图5-4所示。而访问其公有属性strName就不会有问题。,2020/7/14,23,C#程序设计实用教程,5.2.4 类的动态行为:方法,类的属性是客观世界实体性质的抽象,而方法是实体所能执行的操作。 下面来看如何声明其
15、动态方法。同属性一样,类的方法也具有访问属性,如public、private、protected等,其定义格式如下: 修饰符 返回类型 方法名 (参数列表); 下面的例子为Student类定义了公有方法SetAge()和GetAge(),用于设置和获取其静态属性“年龄”。,2020/7/14,24,C#程序设计实用教程,5.2.4 类的动态行为,【例5-3】类的公有方法的示例。 using System; namespace DeclareMethod / 学生类 public class Student /属性 public string strName;/公有属性 private int
16、nAge;/私有属性 /方法. public void SetAge(int _nAge) this.nAge = _nAge; ,2020/7/14,25,C#程序设计实用教程,5.2.4 类的动态行为,public int GetAge() return this.nAge; / Main函数类 class Class1 static void Main(string args) Student s = new Student(); s.SetAge(20);/赋值年龄 Console.WriteLine(s.GetAge();/获取年龄 ,2020/7/14,26,C#程序设计实用教程,
17、5.2.4 类的动态行为,程序中为各个学生定义了公有方法SetAge(),其功能是为类的私有属性“年龄”赋值;同时为学生类定义了获取“年龄”属性值的公有方法GetAge()。 通过SetAge()方法,并传递适当的参数,便可以为学生s的年龄赋值,而通过调用GetAge()方法获取其年龄,并输出。,2020/7/14,27,C#程序设计实用教程,5.2.5 创建类的实例 -对象,类是现实世界中对象或者关系的模拟,是一个抽象的概念。例如,像“学生”这个概念,世界上并没有一个叫做“学生”的活生生的东西,而只有“张三”或者“李四”这些具体的学生实例,这反应了类和对象的关系。 (1)类是具有相同或相似结
18、构、操作和约束规则的对象组成的集合。 (2)对象是某一类的具体化实例,每一个类都具有某些共同特征对象的抽象。 C#使用new关键字来实现实例化类得到一个具体的对象,其格式如下: 类名 对象名=new 类名(参数列表); 在前面的示例中已经用到创建类实例,都是使用new关键字得到一个具体的学生对象。如下列代码所示: Student s = new Student();,2020/7/14,28,C#程序设计实用教程,对象的使用,【例5-2】public和private修饰符的作用。 using System; namespace Example_PublicAndPrivate / 学生类 pu
19、blic class Student /属性 public string strName;/公有属性 private int nAge;/私有属性 /方法. ,/ Main函数类 class Test / 应用程序的主入口点。 static void Main(string args) Student s = new Student(); s.strName = 张三“;/正确 s.nAge = 20;/错误,不能访问 ,5.2.6 继承类,继承的本质是代码重用。当要构造一个新的类时,通常无需从头开始。 例如,在学生类的基础上,可以建立一个“大学生”类。很明显,“大学生”这个类具有自己的新特点
20、,如“所在系”就并不是所有的学生都有的,而是大学生才有的特殊性质。 因此,可以把大学生看作是学生的一种延续,即在继承了学生的属性和方法基础之上,又包含了新的属性或方法。 在构造大学生这个类时,只需在学生类的基础上添加大学生特有的特性即可,而无需从头开始。 此时,称学生类为父类,大学生类为子类。在C#中,用符号“:”来实现类的继承。,2020/7/14,30,C#程序设计实用教程,5.2.6 继承类,【例5-4】类继承的示例。 using System; namespace Example_Inheritance / 学生类 public class Student public string
21、strName;/姓名 public int nAge;/年龄 ,2020/7/14,31,C#程序设计实用教程,5.2.6 继承类,/ 大学生类:继承学生类 public class CollegeStudent : Student public string strInsititute;/所在系 ,2020/7/14,32,C#程序设计实用教程,5.2.6 继承类,/ 程序入口:主函数类 public class MainClass / 主函数 static void Main(string args) Student s = new Student(); s.strName = xiao
22、bao; s.nAge=18; Console.WriteLine(姓名:0,年龄1, s.strName, s.nAge);,2020/7/14,33,C#程序设计实用教程,5.2.6 继承类,/使用子类 Console.WriteLine(-使用子类-); CollegeStudent c = new CollegeStudent(); c.strName = 小宝; c.nAge=23; c.strInsititute = 计算机系; Console.WriteLine(姓名:0,年龄:1岁,所属系:2, c.strName, c.nAge, c.strInsititute); Cons
23、ole.ReadKey(); ,2020/7/14,34,C#程序设计实用教程,5.2.6 继承类,程序运行结果如图5-5所示。 注意:此时,大学生类具有学生类的所有属性和方法,另外,还具有其独自的属性所在系。不难看出,继承就是指一个子类能够直接获得父类的性质或特征,而不必重复定义。显然,继承具有传递性。另外,C#只支持单继承,即一个类只能继承一个父类。,2020/7/14,35,C#程序设计实用教程,5.3 构造函数和析构函数,在实际应用中,方法的定义和调用是很复杂的。在此,将从两个特殊的方法(构造函数和析构函数)入手,对其进行进一步的讨论。 在C#中,构造函数是当类实例化时首先执行的函数。
24、反之,析构函数是当实例(也就是对象)从内存中销毁前最后执行的函数。 这两个函数的执行是无条件的,并且不需要程序手工干预。也就是说,只要定义一个对象或销毁一个对象,不用显式地调用构造函数或析构函数,系统都会自动在创建对象时调用构造函数,而在销毁对象时调用析构函数。,2020/7/14,37,C#程序设计实用教程,5.3.1 构造函数,在实例化对象的时候,对象的初始化是自动完成的,并且这个对象是空的。 有时,我们希望创建一个对象时要为其初始化某些特征,这时就需要用到构造函数。 在C#中,构造函数是特殊的成员函数。 构造函数的特殊性表现在如下几个方面: (1)构造函数的函数名和类的名称一样。 (2)
25、构造函数可以带参数,但没有返回值。 (3)构造函数在对象定义时被自动调用。,2020/7/14,38,C#程序设计实用教程,5.3.1 构造函数,(4)如果没有给类定义构造函数,则编译系统会自动生成一个默认的构造函数。 (5)构造函数可以被重载,但不可以被继承。 (6)构造函数的类型修饰符总是public。如果是private,则表示这个类不能被实例化,这通常用于只含有静态成员的类中。,2020/7/14,39,C#程序设计实用教程,5.3.1 构造函数,【例5-5】通过构造函数,实现在产生一个学生对象时为其完成起名工作。 using System; namespace Example_Con
26、struct / / 学生类 / public class Student public string strName;/域,2020/7/14,40,C#程序设计实用教程,5.3.1 构造函数,/ / 构造函数,为学生起名 / public Student(string _strName) this.strName = _strName; class Class1 static void Main(string args) Student s = new Student(张三); Console.WriteLine(s.strName); ,2020/7/14,41,C#程序设计实用教程,5
27、.3.1 构造函数,注意:在Student类中,定义了方法Student(),注意这个方法与Student类同名。这样,每当实例化一个Student对象时,总会执行这个函数。 在构造函数中可以没有参数,也可以有一个或多个参数。这表明构造函数在类的声明中可以有函数名相同,但参数个数不同或者参数不同的多种形式,这就是构造函数重载。 用new关键字创建一个类的对象时,类名后的一对圆括号提供初始化列表,这实际上就是提供给构造函数的参数。系统根据这个初始化列表的参数个数、参数类型和参数顺序调用不同的构造函数。,2020/7/14,42,C#程序设计实用教程,5.3.1 构造函数,【例5-6】实现Time
28、类的构造函数及其重载。 using System; namespace Example_ConstructOverload class Time public int nHour, nMinute, nSecond; public Time() nHour = nMinute = nSecond = 0; ,2020/7/14,43,C#程序设计实用教程,5.3.1 构造函数,public Time(int Hour) nHour = Hour; nMinute = nSecond = 0; public Time(int Hour,int Minute) nHour = Hour; nMin
29、ute = Minute; nSecond = 0; ,2020/7/14,44,C#程序设计实用教程,5.3.1 构造函数,public Time(int Hour,int Minute,int Second) nHour = Hour; nMinute = Minute; nSecond = Second; class Test static void Main() Time t1, t2, t3, t4;,2020/7/14,45,C#程序设计实用教程,5.3.1 构造函数,/对t1,t2,t3,t4分别调用不同的构造函数 t1 = new Time(); t2 = new Time(1
30、0); t3 = new Time(10, 30); t4 = new Time(10, 30, 30); Console.WriteLine(t1的时间为:0时1分钟2秒, t1.nHour, t1.nMinute, t1.nSecond); Console.WriteLine(t2的时间为:0时1分钟2秒, t2.nHour, t2.nMinute, t2.nSecond); Console.WriteLine(t3的时间为:0时1分钟2秒, t3.nHour, t3.nMinute, t3.nSecond); Console.WriteLine(t4的时间为:0时1分钟2秒, t4.nH
31、our, t4.nMinute, t4.nSecond); ,2020/7/14,46,C#程序设计实用教程,5.3.1 构造函数,程序运行结果如图5-6所示。 注意:实例对象创建时,根据不同的参数调用相应的构造函数完成初始化。,2020/7/14,47,C#程序设计实用教程,5.3.2 析构函数,前面,介绍了使用构造函数在实例化对象时自动完成一些初始化工作。 反之,在销毁对象时,有时候也希望能自动一些做“收尾”任务,例如关闭数据库连接等。C#使用析构函数来完成这个功能。,2020/7/14,48,C#程序设计实用教程,5.3.2 析构函数,析构函数也是类的特殊的成员函数,它主要用于释放类实例
32、。析构函数的特殊性表现在以下几个方面: (1)析构函数的名字也与类名相同,只是需要在其前面加了一个符号“”。 (2)析构函数不接收任何参数,没有任何返回值,也没有任何访问关键字。 (3)当撤销对象时,自动调用析构函数。 (4)析构函数不能被继承,也不能被重载。 注意:另外,如果试图声明其他不与类名相同,但是以“”开头的方法,编译器会产生错误。,2020/7/14,49,C#程序设计实用教程,5.3.2 析构函数,【例5-7】为Student类建立析构函数。 public class Student / / 析构函数 / Student() Console.WriteLine(Call Dest
33、ruct Method.); 当程序使用完一个学生对象后,都会自动调用这个析构函数,输出“Call Destruct Method.”。,2020/7/14,50,C#程序设计实用教程,5.3.2 析构函数,说明:事实上,一般并不需要使用析构函数,.NET Framework提供了默认的析构函数执行内存清理等工作。如果确定需要在销毁对象前,完成一些特殊的任务,才需要使用自定义的析构函数。,2020/7/14,51,C#程序设计实用教程,5.3.2 析构函数,【例5-8】构造函数和析构函数的使用。 using System; namespace Example_ConstructAndDestr
34、uct class Point int x, y, z; public Point() this.z = 0; ,2020/7/14,52,C#程序设计实用教程,5.3.2 析构函数,public Point(int x, int y) this.x = x; this.y = y; this.z = x + y; public int _Z/属性 get return this.z; set this.z = value; ,2020/7/14,53,C#程序设计实用教程,5.3.2 析构函数,Point() Console.WriteLine(Point() is being called
35、.); class Test static void Main() Point p1 = new Point(1, 5); Point p2 = new Point(); Console.WriteLine(p1.z= + p1._Z); Console.WriteLine(p2.z= + p2._Z); ,2020/7/14,54,C#程序设计实用教程,5.4 方法,在前面,对类的方法进行了简单的介绍,也对特殊的类方法构造和析构函数进行了介绍。 在实际应用中,方法的定义和调用要复杂得多。 本节将从输入参数、方法重载等方面,对其进行进一步的讨论。,2020/7/14,55,C#程序设计实用教程
36、,5.4.1 方法的定义及调用,方法是类中用于执行计算或进行其他操作的函数成员。 1. 方法的定义 方法由方法头和方法体组成,其一般定义的格式为: 修饰符返回值类型方法名(形式参数列表) 方法体各语句; ,2020/7/14,56,C#程序设计实用教程,5.4.1 方法的定义及调用,说明: (1)如果省略“方法修饰符”,默认为private,表示该方法为类的私有成员。 (2)“返回值类型”指定该方法返回数据的类型,它可以是任何有效的类型,C#通过方法中的return语句得到返回值。如果方法不需要返回一个值,其返回值类型必须是void。 (3)方法名要求满足C#标识符的命名规则,括号()是方法的
37、标志,不能省略。 (4)“方法参数列表”是逗号分隔的类型、标识符对。这里的参数是形式参数,本质是一个变量,它用来在调用方法时接收传给方法的实际参数的值。如果方法没有参数,那么参数列表为空。,2020/7/14,57,C#程序设计实用教程,5.4.1 方法的定义及调用,【例5-9】方法的定义。 class Motorcycle public void StartEngine() public void AddGas(int gallons) public int Drive(int miles, int speed) return 0; ,2020/7/14,58,C#程序设计实用教程,5.4.
38、1 方法的定义及调用,2. 方法的调用 调用对象的方法类似于访问字段。在对象名称名称之后,依次添加句点、方法名称和括号。参数在括号内列出,并用逗号隔开。因此,可以如下例来调用Motorcycle类的方法。 【例5-10】方法的调用。 Motorcycle moto = new Motorcycle(); moto. StartEngine(); moto. AddGas(15); moto. Drive(5,20);,2020/7/14,59,C#程序设计实用教程,5.4.1 方法的定义及调用,3. 从方法返回 一般来说有两种情况将导致方法返回。 (1) 当遇到方法的结束花括号。 (2)执行到
39、return语句。 有两种形式的return语句:一种用在void方法中(即无需有返回值的方法),另一种用在有返回值的方法中。,2020/7/14,60,C#程序设计实用教程,5.4.1 方法的定义及调用,【例5-11】通过方法的结束花括号返回。 using System; namespace Method class MyClass public void myMethod() int i; for (i = 0; i 10; i+) if (i % 3 = 0) continue; Console.WriteLine(0t, i); ,2020/7/14,61,C#程序设计实用教程,5.4
40、.1 方法的定义及调用,static void Main() MyClass mycls = new MyClass(); mycls.myMethod(); ,程序的运行结果为: ,2020/7/14,62,C#程序设计实用教程,5.4.1 方法的定义及调用,【例5-12】通过方法的return语句返回。 using System; namespace Method class MyClass public void myMethod() int i = 8; if (i = 5) i = i * 2; Console.WriteLine(i); return; ,else i = i *
41、3; Console.WriteLine(i); return; static void Main() MyClass mycls = new MyClass(); mycls.myMethod(); ,2020/7/14,63,C#程序设计实用教程,5.4.1 方法的定义及调用,使用下述形式的return语句从方法返回一个值给调用者: 格式:return value; 【例5-13】通过方法的return语句 返回值。 using System; namespace Method class MyClass public int myMethod() int i = 8; if (i = 5
42、) i = i * 2; return i; ,else i = i * 3; return i; static void Main() MyClass mycls = new MyClass(); Console.WriteLine(mycls.myMethod(); ,2020/7/14,64,C#程序设计实用教程,5.4.2 方法的参数,调用方法时,可以给方法传递一个或多个值。传给方法的值称为实参(argument),在方法内部,接收实参值的变量称为形参(parameter),形参在紧跟着方法名的括号中声明。形参的声明语法与变量的声明语法一样。形参只在方法内部有效,除了将接收实参的值外,
43、它与一般的变量没什么区别。 C#方法的参数类型主要有:值参数、引用参数、输出参数和参数数组。,2020/7/14,65,C#程序设计实用教程,5.4.2 方法的参数,1. 值参数 没有用任何修饰符声明的参数为值参数,它表明实参与形参之间按值传递。 当这个方法被调用时,编译器为值参数分配存储单元,然后将对应的实参的值拷贝到形参中。 实参可以是变量、常量、表达式,但要求其值的类型必须与形参声明的类型相同或者能够被隐式地转化为这种类型。 这种传递方式的好处是在方法中对形参的修改不会影响外部的实参,也就是说数据只能传入方法而不能从方法传出。,2020/7/14,66,C#程序设计实用教程,5.4.2
44、方法的参数,【例5-14】使用值参数。 using System; namespace ValueParameters class MyClass public void Swap(int x, int y) int k; k = x; x = y; y = k; ,2020/7/14,67,C#程序设计实用教程,5.4.2 方法的参数,class Test static void Main() int a = 8, b = 10; Console.WriteLine(a=0,b=1, a, b); MyClass mycls = new MyClass(); mycls.Swap(a, b)
45、; Console.WriteLine(a=0,b=1, a, b); ,程序的运行结果为: a=8,b=10 a=8,b=10,2020/7/14,68,C#程序设计实用教程,5.4.2 方法的参数,2. 引用参数 用ref修饰符声明的参数为引用参数。 引用参数与值参数不同,引用参数并不创建新存储单元,它与方法调用中的实参变量同处一个存储单元。因此,在方法内对形参的修改就是对外部实参变量的修改。 在函数调用中,引用参数必须被赋初值。 在调用时,传递给ref参数的必须是变量,类型必须相同,并且必须使用ref修饰。,2020/7/14,69,C#程序设计实用教程,5.4.2 方法的参数,【例5-
46、15】使用引用参数。 using System; namespace ReferenceParameters class MyClass public void Swap(ref int x, ref int y) int k; k = x; x = y; y = k; ,2020/7/14,70,C#程序设计实用教程,5.4.2 方法的参数,class Test static void Main() int a = 8, b = 10; Console.WriteLine(a=0,b=1, a, b); MyClass mycls = new MyClass(); mycls.Swap(re
47、f a, ref b); Console.WriteLine(a=0,b=1, a, b); ,程序的运行结果为: a=8,b=10 a=10,b=8,2020/7/14,71,C#程序设计实用教程,5.4.2 方法的参数,3. 输出参数 用out修饰符定义的参数称为输出参数。 如果希望方法返回多个值,可使用输出参数。 输出参数与引用参数类似,它也不产生新的存储空间。 两者的区别在于:out参数只能用于从方法中传出值,而不能从方法调用处接受实参数值;在方法体内out参数被认为是未赋过值的,所以在方法结束之前应该对out参数赋值。,2020/7/14,72,C#程序设计实用教程,5.4.2 方法
48、的参数,【例5-16】使用输出参数。 using System; namespace OutputParameters public class Student public string strName;/姓名 public int nAge; /年龄 /构造函数 public Student(string _strName, int _nAge) strName = _strName; nAge = _nAge; ,2020/7/14,73,C#程序设计实用教程,5.4.2 方法的参数,/长大_nSpan岁 public void Grow(int _nSpan, out int _nOu
49、tCurrentAge) nAge += _nSpan; _nOutCurrentAge = nAge; public class Test static void Main() Student s = new Student(张三, 21); int nCurrentAge; s.Grow(3, out nCurrentAge); Console.WriteLine(s.nAge); /输出24 ,2020/7/14,74,C#程序设计实用教程,5.4.2 方法的参数,程序的输出结果如下: 24 注意:在上例中,在调用时需要在输入参数前加out关键字。,2020/7/14,75,C#程序设计
50、实用教程,5.4.2 方法的参数,4. 参数数组 有时候,在调用一个方法时,预先不能确定参数的数量、数据类型等,怎么办呢? 一种解决方案是使用params关键字。params关键字指明一个输入参数,此输入参数将被看作为一个参数数组,这种类型的输入参数只能作为方法的最后一个参数。以下例说明其功能。,2020/7/14,76,C#程序设计实用教程,5.4.2 方法的参数,【例5-17】使用参数数组。 using System; namespace ParameterArray public class Student public string strName;/姓名 public int nAg
51、e;/年龄 public System.Collections.ArrayList strArrHobby = new System.Collections.ArrayList();/爱好,2020/7/14,77,C#程序设计实用教程,5.4.2 方法的参数,/ / 构造函数 / public Student(string _strName, int _nAge) this.strName = _strName; this.nAge = _nAge; / / 为爱好赋值 / public void SetHobby(params string _strArrHobby) for (int i
52、 = 0; i _strArrHobby.Length; i+) this.strArrHobby.Add(_strArrHobbyi); ,2020/7/14,78,C#程序设计实用教程,5.4.2 方法的参数,class Test static void Main(string args) Student s = new Student(张三, 20); s.SetHobby(游泳, 篮球, 足球); for (int i = 0; i s.strArrHobby.Count; i+) Console.WriteLine(s.strArrHobbyi); ,2020/7/14,79,C#程
53、序设计实用教程,5.4.2 方法的参数,程序的输出结果如下: 游泳 篮球 足球 注意:上例为Student类实现了一个爱好赋值方法,用于确定学生的爱好。因为实现无法确定学生的爱好数目,因此可以使用params参数来接收多个字符串参数,并整体作为数组传递给方法。,2020/7/14,80,C#程序设计实用教程,5.4.3 方法的重载,有时,对于类需要完成的同一个功能,要求可能比较复杂。例如,对学生类而言,如果想要使其具有一个“成长”方法,但是这个方法,可能是使学生增加一岁,也可能是增加指定的岁数,该如何解决这个问题呢? C#使用重载技术来完成这个功能。 重载是指允许存在多个同名函数,而这函数的参
54、数不同(或许是参数个数不同,或许参数类型不同,或许两者都不同)。在调用这个方法时,编译器可以按照输入的参数去调用适当的方法。 下例所示代码完成本节所提出的学生“成长”问题。,2020/7/14,81,C#程序设计实用教程,5.4.3 方法的重载,【例5-18】方法的重载。 using System; namespace MethodOverload / / 学生类 / public class Student /属性 public string strName;/姓名 public int nAge;/年龄,2020/7/14,82,C#程序设计实用教程,5.4.3 方法的重载,/ / 成长1
55、岁 / public void Grow() this.nAge+; / / 成长_nAgeSpan岁 / public void Grow(int _nAgeSpan) this.nAge += _nAgeSpan; ,2020/7/14,83,C#程序设计实用教程,5.4.3 方法的重载,/ / Main函数类 / class Class1 static void Main(string args) Student s = new Student(); s.strName = 张三; s.nAge = 20; s.Grow(); Console.WriteLine(s.nAge);/输出2
56、1 s.Grow(2); Console.WriteLine(s.nAge);/输出23 ,2020/7/14,84,C#程序设计实用教程,5.4.3 方法的重载,程序运行如果如下: 21 23 注意:在示例中,定义了学生类,在类中实现了两个Grow()方法;前一个Grow()方法,没有任何输入参数,其功能为使学生年龄加1,后一个同名方法Grow(),带有一个参数_nAgeSpan,其功能为使学生年龄加nAgeSpan。在主函数中,分别调用学生类的Grow()方法,并输入不同的参数,从而得到不同的结果。这样,就可以使用同样的方法名,完成功能类似、具体实现不同的任务了。,2020/7/14,85,C#程序设计实用教程,5.4.4 静态方法和非静态方法,使用static修饰符的方法称为静态方法,没有使用static修饰符的方法称为非静态方法。 静态方法和非静态方法的区别是:静态方法表示类所具有的行为,而非其某个具体对象所具有的行为。例如学生分班这项任务,就是全体学生集体的事情,而非某个学生的事情。 静态
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年国网冀北电力有限公司人员招聘笔试参考题库及答案详解
- 2026年中国石油上海销售分公司人员招聘笔试参考题库及答案详解
- 2027届浙江省杭州市中考数学模拟试卷(含答案解析)
- 2026河北石家庄无极县从服务期满“三支一扶”志愿者专项招聘事业单位人员4名笔试备考题库及答案解析
- 2026年国联证券人员招聘考试备考题库及答案详解
- 2026年其他烟草制品制造行业现状及前景展望报告及未来五至十年智能体与场景落地
- 2026年皮革制品制造行业市场运营态势报告及未来五至十年平台化与生态化发展
- 2026年宁夏旅游投资集团公司人员招聘参考题库及答案详解
- 2026年其他酒制造行业产业研究报告及未来五至十年政策驱动与市场机遇展望
- 2026年德宏市烟草专卖局人员招聘参考题库及答案详解
- 辽宁石化职业技术学院单招职业技能考试题库及答案
- 2026-2027学年四年级上册数学单元全真模拟培优卷(人教版)第4单元 加法模型和乘法模型
- 2026年全国职业病诊断医师培训职业性化学中毒复习题及答案
- 徐工25吨吊车使用说明书
- 帕金森病深部脑刺激(DBS)手术
- 平面设计师招聘笔试题及解答(某大型国企)2025年
- 2026年温州市房地产行业分析报告及未来发展趋势报告
- 老师给的立式多喷嘴水喷射真空泵设计课程设计模板
- 实施指南(2025)《HGT 4615-2023 增塑剂 柠檬酸三丁酯(TBC)》
- 2025年南航乘务英语题库及答案
- 餐饮行业安全隐患排查情况报告范文
评论
0/150
提交评论