目录
4.1 类的概述
类是一种活动的数据结构
4.2 程序和类:一个快速实例
4.3 声明类
4.4 类成员
4.4.1 字段
1.显示和隐式字段初始化
2. 声明多个字段
4.4.2 方法
4.5 创建变量和类的实例
4.6 为数据分配内存
合并这两个步骤
4.7 实例成员
4.8 访问修饰符
私有访问和共有访问
1.公有访问和私有访问图示
2.成员访问实例
4.9 从类的内部访问成员
4.10 从类的外部访问成员
4.11 综合应用
在上一章中,我们看到C#提供了用户6种用户定义类型。其中最重要的,也是首先要阐述的是类。因为类在C#中是个很大的主题,关于它的讨论将会延伸到接下来的几章。
在面向对象的分析和设计产生之前,程序员们仅把程序当做指令的序列。那时的焦点主要放在指令的组合和优化上。随着面向对象的出现,焦点从优化指令转移到组织程序的数据和功能上来。程序的数据和功能被组织为逻辑上相关的数据项和函数的封装集合,并被称为类。
类是一个能存储数据并执行代码的数据结构。它包含数据成员和函数成员。
一个C#类可以有任意数目的数据成员和函数成员。成员可以是9种可能的成员类型的任意组合。这些成员类型如表4-1所示。本章将会阐述字段和方法。
一个运行中的C#程序是一组相互作用的类型对象,他们中的大部分是类的实例。例如,假设有一个模拟扑克牌游戏的程序。当程序运行时,他有一个名为Dealer的类的实例,它的工作就是运行游戏。还有几个名为Player的类实例,他们代表游戏的玩家。
Dealer对象保存纸牌的当前状态和玩家数目等信息。它的动作包括洗牌和发牌。
Player类有很大不同。它保存玩家名称以及用于押注的钱的信息,并实现如分析玩家当前手上的牌和出牌这样的动作。运行中的程序如图4-1所示。类名显示在方框外面,实例名显示在方框内。
一个真正的程序无疑会包含除Dealer和Player之外的许多其他的类,还会包括像Card和Deck这样的类。每一个类都模拟某种扑克牌游戏中的事物。
或许你能猜到,虽然类型int、double和char由C4#定义,但像Dealer和Player这样的类不是由语言定义的。如果想在程序中使用他们,你必须自己定义,通过编写类的声明定义类。
类的声明定义类的特征和成员。它并不创建类的实例,但创建了用于创建实例的模板。类的声明提供下列内容:
下面是一个最简单的类声明语法示例。大括号包含了成员的声明,他们组成了类主体。类成员可以在类主体内部以任何顺序声明。这意味着成员的声明完全可以引用另一个在后面的类声明中才定义的成员。
字段和方法是最重要的类成员类型。字段是数据成员,方法是函数成员。
字段是隶属于类的变量。
声明一个字段最简单的语句如下:
因为字段是一种变量,所以字段初始化语句在语法上和上一章所描述的变量初始化语句相同。
class Myclass
{
int F1 = 17; //字段初始值
}
例如,下面的代码声明了4个字段,前两个字段被隐式初始化,另外两个字段被初始化语句显示初始化。
可以通过用逗号分隔名称的方式,在同一条语句中声明多个相同类型的字段,但是不能再一个声明中混合不同的类型。例如,可以把之前的4个字段声明结合成两条语句,并有相同的语义结果。
方法是具有名称的可执行代码块,可以从程序的很多不同的地方执行,甚至从其他程序中执行。(还有一种没有名称的匿名方法,将在第13章讨论)
当方法被调用(call/invoke)时,他执行自己所含的代码,然后返回到调用它的代码并继续执行调用代码。有些方法返回一个值到他们被调用的位置。方法相当于C++中的成员函数。
声明方法最简单的语法包括以下组成部分。
例如,下面的代码声明了一个类,带有一个名称为PrintNums的简单方法。从这个声明中可以看出下面几点关于PrintNums的情况:
类的声明只是用于创建类的实例的蓝图。一旦类被声明,就可以创建类的实例。
图4-2阐明了如何定义保存引用的变量。左边顶端的代码是类Dealer的声明,下面是类Program的声明,它包含Main方法。Main声明了Dealer类型的变量TheDealer,因为变量没有初始化,它的值是未定义的,如图4-2的右边所示。
声明类类型的变量所分配的内存是用来保存引用的,而不是用来保存类对象实际数据的。要为实际数据分配内存,需要使用new运算符。
要分配和初始化用于保存类实例数据的内存,需要做的工作就是这些。下面是使用new运算符创建对象创建表达式,并把它的返回值赋给类变量的一个例子:
图4-3左边的代码展示了用于分配内存并创建类Dealer实例的new运算符,随后实例被赋值给类变量。右边的图展示了内存的结构。
可以将这两步骤合并起来,用对象创建表达式来出初始化变量。
类声明相当于蓝图,通过这个蓝图想创建多少个类的实例都可以。
下面代码是实例成员的示例,展示了由3个Player类实例的扑克牌程序。图4-4表明每个实例的Name字段都有不同的值。
从类的内部,任何函数成员都可以使用成员的名称访问类中任意的其他成员。
访问修饰符是成员声明的可选部分,指明程序的其他部分如何访问成员。访问修饰符放在简单声明形式之前。下面是字段和方法声明的语法:
5种成员访问控制如下。本章将阐明前两种,其他的在第7章阐述。
私有成员只能从声明它的类的内部访问,其他的类不能看见或访问它们。
例如,下面的两个声明都指定了private int 成员:
实例的公有成员可以被程序中的其他对象访问。必须使用public访问修饰符指定公有访问。
本文中的插图把类表示为标签框,如图4-5所示;
类C1声明了公有和私有的字段和方法,图4-6阐明了类C1的成员的可见性。
如前所属,类的成员仅用其他类成员的名称就可以访问它们。
例如,下面的类声明了类的方法对字段和其他方法的访问。即使字段和两个方法被声明为private,类的所有成员还是都可以被类的任何方法(或者任何函数成员)访问。图4-7阐明了这段代码。
要从类的外部访问实例成员,必须包括变量名称和成员名称,中间用句点(.)分隔。这称为点运算符(dot-syntax notation),将会在以后更详细地讨论。
例如,下面代码的第二行展示了一个从类的外部访问方法的实例:
举个例子,下面的代码声明了两个类:DaysTemp和Program。
下面的代码创建两个实例并把它们的引用保存在名称为t1和t2的变量中。图4-8阐明了内存中的t1和t2.这段代码示范了目前为止讨论的使用的3中行为: