购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2 类

类是面向对象的程序设计的基本构成模块。从定义上讲,类是一种数据结构,这种数据结构可能包含数据成员、函数成员以及其他的嵌套类型,其中数据成员类型有常量域和事件函数、成员类型、方法属性、索引指示器、操作符、构造函数和析构函数。

2.2.1 类的声明

类的声明格式如下:

其中,attributes、class-modifiers、class-base和class-body为可选项,attributes为属性集,class-modifiers为类的修饰符,关键词class后跟随类的名称,identifier class-base和class-body表示继承方式和基类名类的修饰符。

类的修饰符可以是以下几种之一或它们的组合,在类的声明中同一修饰符不允许出现多次:

1)new仅允许在嵌套类声明时使用,表明类中隐藏了由基类中继承而来的与基类中同名的成员。

2)public表示不限制对该类的访问。

3)protected表示只能从所在类和所在类派生的子类进行访问。

4)internal只有其所在类才能访问。

5)private只有.Net包中的应用程序或库才能访问。

6)abstract抽象类不允许建立类的实例。

7)sealed密封类不允许被继承。

使用new关键字可以建立类的一个实例,代码如下:

在类B的方法F中创建了一个类A的实例、类的继承声明。

我们使用如下代码表示类B从类A中继承:

有关C#中的继承机制,我们放在2.5节中进行详细讨论,在这里要事先声明的一点是C#中的类只支持单继承。

2.2.2 类的成员

类的成员可以分为类本身所声明的成员以及从基类中继承而来的类的成员,有以下类型:

1)成员常量:代表与类相关联的常量值。

2)域:即类中的变量。

3)成员方法:复杂执行类中的计算和其他操作。

4)属性:用于定义类中的值并对它们进行读写。

5)事件:用于说明发生了什么事情。

6)索引指示器:允许像使用数组那样为类添加路径列表。

7)操作符:定义类中特有的操作。

8)构造函数和析构函数:分别用于对类的实例进行初始化和销毁,包含可执行代码的成员被认为是类中的函数成员,这些函数成员有方法属性、索引指示器、构造函数和析构函数。

2.2.2.1 对类的成员的访问

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

1.公有成员

C#中的公有成员提供了类的外部界面,允许类的使用者从外部进行访问。公有成员的修饰符为public,这是限制最少的一种访问方式。

2.私有成员

C#中的私有成员仅限于类中的成员可以访问。从类的外部访问私有成员是不合法的,如果在声明中没有出现成员的访问修饰符,按照默认方式成员为私有的。私有成员的修饰符为private。

3.保护成员

为了方便派生类的访问,又希望成员对于外界是隐藏的,这时可以使用protected修饰符声明成员为保护成员。

4.内部成员

使用internal修饰符的类的成员是一种特殊的成员,这种成员对于同一包中的应用程序或库是透明的,而在包.Net之外是禁止访问的。

使用下面的例子说明一下类的成员的访问修饰符的用法:

程序清单 2-6:

2.2.2.2 this保留字

保留字this仅限于在构造函数类的方法和类的实例中使用,它有以下含义:

1)在类的构造函数中出现的this:作为一个值类型,它表示对正在构造的对象本身的引用。

2)在类的方法中出现的this:作为一个值类型,它表示对调用该方法的对象的引用。

3)在结构的构造函数中出现的this:作为一个变量类型,它表示对正在构造的结构的引用。

4)在结构的方法中出现的this:作为一个变量类型,它表示对调用该方法的结构的引用,除此以外,在其他地方使用this保留字都是不合法的。

下面的代码演示了如何使用this保留字:

程序清单 2-7:

程序运行的结果应该是

下面再举一个例子来说明this的用法:

程序清单 2-8:

程序用于求某个整数是否为另一个整数的阶乘,如果是,类Fact的方法GetFact返回该整数,否则GetFact返回-1。实际上在C#内部,this被定义为一个常量,因此使用this++、this--这样的语句都是不合法的,但是this可以作为返回值来使用。我们知道在Windows操作系统中,当前窗口总是被加亮显示,我们称该窗口被激活。例如在Word中,我们可以同时打开多个文档,每个文档窗口作为Word主窗口的一个子窗口,其中只有一个子窗口是当前激活的窗口。如果Word没有打开任何文档,则主窗口作为当前激活的窗口。

下面的例子中,我们声明了一个窗口类Window。假设类Window一次最多可以同时打开五个子窗口,Window的方法GetActiveWindow用于返回当前激活的窗口。如果打开了子窗口,则返回该子窗口的实例,否则返回主窗口本身。

程序清单 2-9:

2.2.2.3 静态成员和非静态成员

若将类中的某个成员声明为static,该成员称为静态成员。类中的成员要么是静态的要么是非静态的,一般静态成员是属于类所有的,非静态成员则属于类的实例对象。

以下示例代码演示了如何声明静态和非静态成员:

程序清单 2-10:

类的非静态成员属于类的实例,每创建一个类的实例都在内存中为非静态成员开辟了一块区域;而类的静态成员属于类,为这个类的所有实例所共享,无论这个类创建了多少个副本,一个静态成员在内存中只占有一块区域。

2.2.2.4 成员常量

再看一个成员常量的声明例子:

关键字const用于声明后跟数据类型的常量,可以加上new、public、protected、internal、private修饰符。

可以用一条语句同时声明多个常量,比如上例可以写成:

2.2.3 构造函数和析构函数

2.2.3.1 构造函数

构造函数用于执行类的实例的初始化。每个类都有构造函数,即使没有声明它,编译器也会自动提供一个默认的构造函数,在访问一个类时将最先执行构造函数中的语句,实际上任何构造函数的执行都隐式地调用了系统提供的默认的构造函数base()。

如果在类中声明了如下的构造函数:

如果在类中声明了如下的构造函数:

C(…){…}

它等价于

C(…):base(){…}

使用构造函数请注意以下几个问题:

1)一个类的构造函数通常与类名相同。

2)构造函数不声明返回类型。

3)构造函数一般是public类型的,如果是private类型的,表明类不能被实例化,这通常用于只含有静态成员的类。

4)在构造函数中,不要对类的实例做初始化以外的事情,也不要尝试显式地调用构造函数。

下面的例子示范了构造函数的使用:

上面的例子中,类A同时提供了不带参数和带参数的构造函数。构造函数可以是不带参数的,这样对类的实例的初始化是固定的。有时在对类进行实例化时,需要传递一定的数据来对其中的各种数据进行初始化,使得初始化不再是一成不变的,这时可以使用带参数的构造函数来实现对类的不同实例的初始化。在带有参数的构造函数中,类在实例化时必须传递参数,否则该构造函数不被执行。

让我们回顾一下程序清单2-6中关于车辆的类的代码示例,我们在这里添加构造函数,验证一下构造函数中参数的传递。

程序清单 2-11:

程序的运行结果为

2.2.3.2 析构函数

在类的实例超出范围时,我们希望确保它所占的系统资源能被收回,C#中提供了析构函数,用于专门释放被占用的系统资源。

析构函数的名字与类名相同,只是在前面加了一个符号~。析构函数不接受任何参数,也不返回任何值。如果你试图声明其他任何一个以符号~开头而不与类名相同的方法,和试图让析构函数返回一个值一样,编译器都会产生一个错误。

析构函数不能是继承而来的,也不能显式地调用。当某个类的实例被认为不再有效符合析构的条件,析构函数就可能在某个时刻被执行。C++的程序员常常需要在析构函数中写上一系列delete语句来释放存储,而在C#中我们不必再为此担心了,垃圾收集器会帮助我们完成这些易被遗忘的工作。 jCbOpwrHRyo/fzstWNoYYuJu+JkXRbjekfFofn2SZ/K4HEVpGM9dMwjTo0n3nYDf

点击中间区域
呼出菜单
上一章
目录
下一章
×