c技术第7章面向对象的程序设计

本章要点:

面向对象的基本概念

类的定义与对象的声明

构造函数和析构函数

类的静态成员和实例成员

方法重载及运算符重载的编程实现

类的继承与多态性的编程实现

类的属性的实现

7.1循序渐进学理论

7.1.1面向对象程序设计概述

1.面向对象程序设计的由来

面向对象的程序设计是一种基于结构分析的、以数据为中心的程序设计方法。面向对象的程序设计方法总体思路是:将数据及处理这些数据的操作都封装(Encapsulation)到一个称为类(Class)的数据结构中,在程序中使用的是类的实例——对象。对象是代码与数据的集合,是封装好了的一个整体,对象具有一定的功能。也就是说对象是具有一定功能的程序实体。程序是由一个个对象构成的,对象之间通过一定的“相互操作”传递消息,在消息的作用下,完成特定的功能。

2.面向对象程序设计的基本概念

(1)类和对象

通常把具有同样性质和功能的东西所构成的集合叫作类。

(2)属性、方法与事件

属性是对象的状态和特点。

方法是对象能够执行的一些操作,它体现了对象的功能。

事件是对象能够识别和响应的某些操作。

(3)封装

所谓的封装,就是将用来描述客观事物的一组数据和操作组装在一起,形成一个类。

(4)继承

类之间除了有相互交流或访问的关系以外,还可能存在着一种特殊的关系,这就是继承。在VisualC#中只支持单继承,即一个派生类只能有一个基类。

(5)重载

重载指的是方法名称一样,但如果参数不同,就会有不同的具体实现。重载主要有两类:方法重载及运算符重载。

(6)多态性

所谓多态性就是在程序运行时,面向对象的语言会自动判断对象的派生类型,并调用相应的方法。

7.1.2类和对象的声明

1.类的声明

[格式]:[类修饰符]class类名[:基类类名]

{

成员定义列表;

}

定义一个Student类,用来对学生的信息和功能进行描述。假设学生具有学号、姓名、年龄、性别、平均成绩等特征,并且具有设置学生特征和显示学生特征的功能。

2.对象的声明

[格式]:类名  实例名=new类名([参数]);3.类的成员

(1)类成员的分类

类的具体成员如下。

常量:用来定义与类相关的常量值。

字段:类中的变量,相当于C++中的成员变量。

类型:用来定义只能在类中使用的局部类型。

方法:完成类中各种计算或功能的操作。

属性:定义类的特征,并对它们提供读、写操作。

事件:由类产生的通知,用于说明发生了什么事情。

索引器:允许编程人员在访问数组时,通过索引器访问类的多个实例。又称下标指示器。

运算符:定义类的实例能使用的运算符。

构造函数:在类被实例化时首先执行的函数,主要是完成对象初始化操作。

析构函数:在对象被销毁之前最后执行的函数,主要是完成对象结束时的收尾操作。

(2)类成员的可访问性

在编写程序时,可以对类的成员使用不同的访问修饰符,从而定义它们的访问级别,即类成员的可访问性(Accessibility)。

在C#中,根据类成员的可访问性可以把类成员分成四类,分别是公有成员(public)、私有成员(private)、保护成员(protected)、内部成员(internal)。

(3)类的静态成员和实例成员

类的成员又可以分成静态成员和非静态成员。在声明成员时,如果在语句前加上static保留字,则该成员是静态成员,如果没有static保留字,则成员是非静态成员。二者最重要的区别是:静态成员属于类所有,非静态成员属于类的实例所有,所以又称实例成员。

7.1.3类的构造函数和析构函数

1.构造函数

构造函数主要用来为对象分配存储空间,完成初始化操作(如给类的成员变量赋值等)。在C#中,类的构造函数遵循以下规定。

(1)构造函数的函数名和类的名称一样。

(2)当某个类没有构造函数时,系统将自动为其创建构造函数,这种构造函数称为默认构造函数。如例7-2中默认的构造函数为:

Example1()

{

};

(3)构造函数的访问修饰符总是public。如果是private,则表示这个类不能被实例化,这通常用于只含有静态成员的类中。

(4)构造函数由于不需要显式调用,因而不用声明返回类型。

(5)构造函数可以带参数也可以不带参数。

2.析构函数

析构函数在对象销毁时被调用,常用来释放对象占用的存储空间。析构函数具有以下特点。

(1)析构函数不能带有参数。

(2)析构函数不能拥有访问修饰符。

(3)不能显式地调用析构函数。

(4)析构函数的命名规则是在类名前加上一个“~”号。如上例的Example1类的析构函数为:

~Example1()

{

};

(5)析构函数在对象销毁时自动调用。

类的构造函数和析构函数的演示。(程序代码详见例7-3)[执行结果]

7.1.4类的方法及方法的重载

1.方法的定义

[格式]:[方法修饰符]返回值类型方法名([参数列表])

{方法实现部分;

}

2.静态方法和非静态方法

对于静态方法和非静态方法,只需抓住以下几点:(1)静态方法属于类所有,非静态方法属于类定义的对象所有;(2)非静态方法可以访问类中包括静态成员在内的所有成员,而静态方法只能访问类中的静态成员。

静态方法和动态方法的演示。请观察并分析下列程序的执行结果。(程序代码详见例7-4)

[执行结果]

3.参数数组

关于参数数组,需掌握以下几点。

(1)若形参表中含一个参数数组,则该参数数组必须位于形参列表的最后;

(2)参数数组必须是一维数组;

(3)不允许将params修饰符与ref和out修饰符组合起来使用;

(4)与参数数组对应的实参可以是同一类型的数组名,也可以是任意多个与该数组的元素属于同一类型的变量;

(5)若实参是数组则按引用传递,若实参是变量或表达式则按值传递。

参数数组的演示。请观察并分析下列程序的执行结果。(程序代码详见例7-5)

[执行结果]

4.方法的重载

方法重载是指同样的一个方法名,有多种不同的实现方法。方法重载的格式是在一个类中两次或多次定义同名的方法,这些同名的方法包括从基类继承而来的方法,这些方法名称相同,但每个方法的参数类型或个数不同,从而便于在用户调用方法时系统能够自动识别应调用的方法。

方法重载的演示。请观察并分析下列程序的执行结果。(程序代码详见例7-6)

[执行结果]

7.1.5运算符重载

在C#中,运算符重载在类中进行声明,声明的格式如下。

[格式]:返回值类型operator运算符(运算对象列表)

{

重载的实现部分;

};

在C#中,可以重载的运算符主要有:

+-!~++--truefalse

*/%

^==!===

不能重载的运算符有:.

=

?:newtypeofsizeofis

运算符重载的演示。请观察并分析下列程序的执行结果。(程序代码详见例7-7)

[执行结果]

7.1.6域与属性

1.域

域又称字段,它是类的一个成员,这个成员代表与对象或类相关的变量。域的定义格式如下。

[格式]:[域修饰符]域类型域名;

域的演示。请观察并分析下列程序的执行结果。(程序代码详见例7-8)

[执行结果]

2.属性

属性是对现实世界中实体特征的抽象,它提供了一种对类或对象特性进行访问的机制。属性的声明格式如下。

[格式]:[属性修饰符]类型说明符属性名{访问声明}属性的演示。请观察并分析下列程序的执行结果。(程序代码详见例7-9)

[执行结果]

7.1.7this关键字

this关键字用来引用类的当前实例,成员通过this关键字可以知道自己属于哪一个实例。this关键字只能用在类的构造函数、类的实例方法中,在其它地方(如静态方法中)使用this关键字均是错误的。

7.1.8类的继承

继承是面向对象程序设计中实现代码重用的重要机制之一,它起源于现实世界中事物之间的联系。

类的继承的基本格式与功能如下。

[格式]:

class派生类类名:基类类名

{成员声明列表;

}

类继承的演示。请观察并分析下列程序的执行结果。(程序代码详见例7-10)

[执行结果]

7.1.9多态性

多态性是指同一操作作用于不同类的实例,这些类对它进行不同的解释,从而产生不同的执行结果的现象。在C#中有两种多态性:编译时的多态性和运行时的多态性。

运行时的多态性是通过继承和虚成员来实现的。运行时的多态性是指系统在编译时不确定选用哪个重载方法,而是直到程序运行时,才根据实际情况决定采用哪个重载方法。

编译时的多态性具有运行速度快的特点,而运行时的多态性则具有极大的灵活性。

虚函数与多态性的演示。请观察并分析下列程序的执行结果。(程序代码详见例7-11)

[执行结果]

7.1.10密封类与抽象类

把一个类声明为密封类的原因是为了防止该类被其它类继承,密封类的声明方法是在类名前加上sealed修饰符。

抽象类表示一种抽象的概念,一般用于为派生类提供公共接口。在声明类时,在类名前有abstract修饰符则表示该类为抽象类。抽象类只能作为其他类的基类,不能被实例化,在抽象类中可以包含抽象方法和抽象访问器。

7.2典型实例练能力

7.2.1典型实例一:Time类的创建与演示

编写一个名为Time1的类,该类能够存放时间信息,并且具有设置时间和显示时间的功能。然后编程对该类进行测试。测试界面如图7-1所示。

7.2.2典型实例二:复数“*”运算及复数值设置的实现

编写一个复数类,该复数类具有以下功能:(1)乘法运算的功能。如a和b分别是该复数类的两个实例,则可以进行a*b的运算,运算结果是一个复数,该复数是复数a和复数b的乘积。(2)对复数值进行设置的功能,有两种设置方法,分别对复数的实部(虚部为0)进行设置、对复数的实部和虚部同时进行设置。然后编程进行验证。验证界面如图7-2所示。

7.3上机练习重应用

7.3.1上机练习一:栈模型的实现

栈是一种重要的数据结构,在内存中占用连续的存储单元。栈有两个端点,固定的栈底和浮动的栈顶。为指示栈顶位置还应设一个指示成员变量(称为栈顶指示器)。栈有两种基本操作:push(压栈)和pop(出栈),压栈是向栈顶位置写入一个元素,然后使栈顶指示器加1,出栈是先使栈顶指示器减1,再把该位置的元素读出来。栈及其操作模型如图7-3所示,sp代表栈顶指示器。请编程实现栈的模型并对之进行测试,测试的界面如图7-4所示。

7.3.2上机练习二:从shape类派生出Rectangle、Circle等具体形状类

定义一个shape抽象类,利用它作为基类派生出Rectangle、Circle等具体形状类,已知具体形状类均具有两个方法GetArea和GetPerim,分别用来求形状的面积和周长。最后编写一个测试程序对产生的类的功能进行验证,验证程序的运行界面如图7-5所示。




转载请注明:http://www.aierlanlan.com/cyrz/974.html