1
第 6章 类
6.1 面向对象程序设计
6.2 类声明
6.3 类成员
6.4 类与结构
6.5 构造函数和析构函数
6.6 常量
6.7 字段
6.8 运算符重载
2
6.1.1 面向对象程序设计的基本概念面向对象 =对象 +类 +继承 +通信
( 1)抽象
( 2)封装
( 3)继承
( 4)多态性
3
6.1.2 类与对象
1.对象( object)
对象指的是一个实体的实例,在这个实体中包括了特定的属性数据和对这些数据进行操作的函数。
封装性,继承性,多态性
2.类( class)
类是一组具有相同数据结构和相同操作的对象的集合。
在一个类中,每个对象都是类的实例,可以使用类中提供的方法。
创建类的对象的操作,被称为类的实例化。 返回目录
4
一个类就是一个数据结构,可以包含数据成员(常量、字段和事件)、函数成员
(方法、属性、下标指示器、操作符、构造函数和析构函数)和嵌套的类型。
类声明语句声明一个新类,其语法格式为:
[特征 ] [修饰符 ] class 类名 [:基类名和任何实现接口的列表 ]
{
类体
}
5
6.2.1 类修饰符
C#支持的类修饰符有,new,public、
protected,internal,private,abstract和
sealed。
类声明中的类修饰符可以是上面几种之一或是它们的组合。
1.抽象类
2.密封类
6
6.2.2 类的基本规范
如果类声明时指定了基类的类型,那么就表示指定了当前声明的类的直接基类。但是如果类在声明时没有指定基类,或者基类仅列出了一些接口类型,那么当前声明的类的基类假定为 object。
新派生的类必须可以访问其直接基类。
程序员在定义新类时不能以下列类为基类:
System.Array,System.Delegate,
System.Enum,System.ValueType
返回目录
7
6.3.1 类继承
创建派生类要在派生类的名字后面加上冒号
“:”,后面再跟上基类的名字。
派生类继承了基类的所有成员,包括成员变量和方法。派生类可以选择是否自己重新实现基类方法,如需重新实现可以用关键字
new修饰新方法,它表示派生类故意隐藏和替代了基类方法。
8
类继承有以下几点需要注意的:
( 1)如果一个类是从其他类派生的,那么该类也继承其直接基类的所有成员,但基类的构造函数和析构函数除外。
( 2)继承具有传递性。
( 3)派生类可以扩展它的基类。
( 4)基类的构造函数和析构函数不能被继承,但是可以继承的其他成员的存取权限可能会影响到成员在类中的访问。
( 5)派生类可以隐藏继承成员的实现。
( 6)对一个派生类实例的引用可以当成是对该类的基类实例的引用。
( 7)类可以声明虚方法、虚属性和虚下标指示器,
并且派生类可以重载这些函数成员的实现,这样就使类的多态性得以实现。
9
6.3.2 new修饰符
派生类可以声明特定的成员类隐藏基类的相应成员,这种隐藏不是一种错误,但是编译器在编译阶段会给出警告。为了禁止此警告,
派生类成员的声明可以包含 new修饰符以指出该派生成员将隐藏基类成员。
但是如果某派生类成员声明时并不是为了隐藏基类某成员,此时再加 new修饰符就会引起编译警告。
10
6.3.3 静态成员和实例成员
1.静态成员如果字段、方法、属性、事件、运算符或构造函数声明时指定了 static修饰符,就等于声明了一个静态成员。另外,一个常量或类型声明时都隐式地声明了一个静态成员。
2.实例成员如果字段、方法、属性、事件、下标指示器、构造函数或析构函数声明时没有指定 static修饰符,那么此时声明的是一个实例成员(也称为非静态成员)。
11
6.3.4 嵌套类
类都有成员,而类的成员是另一个用户定义类是完全可能的。
被包含的内部类称为嵌套类( nested class),
而包含它的类称为外层类( outer class)。
嵌套类可以对外层类的所有成员进行访问。嵌套类的方法可以访问外层类的私有成员。
嵌套类可以对其他所有类隐藏。
返回目录
12
6.4.1 结构的定义和使用
结构类型的一般定义形式为:
[特征 ] [修饰符 ] struct 结构名 [:接口列表 ]
{
结构体
}
13
6.4.2 结构的嵌套
和类一样,结构中可以包含其他数据类型,
这其中也包括结构。
14
6.4.3 结构和类的区别
1.关于类型
2.关于继承
3.关于定义构造函数
4.关于初始化
5.关于创建对象的方法返回目录
15
6.5.1 实例构造函数
构造函数的定义格式为:
[特征 ] [修饰符 ] 构造函数名 (参数表 )[:base([参数表 ])|:this([参数表 ])]
{
代码
}
16
1.缺省构造函数如果一个 C#类没有声明自己的构造函数,
则编译器会自动建立一个缺省的构造函数。
2.私有构造函数如果一个类的构造函数仅有一个,并且声明为 private类型,那么除了那些嵌套在该类中的类,该类不能作为其他类的基类,
并且在程序中不能创建该类的实例。
3.构造函数的参数在带有参数的构造函数中,类在实例化时必须传递参数,否则该构造函数不被执行。
17
6.5.2 静态构造函数
当构造函数前有 static修饰符时,该构造函数为静态构造函数。
静态构造函数不能带有任何参数,且其定义前不能再出现其他任何修饰符。
C#类的静态构造函数不能被显式调用,它是自动被调用的。
18
6.5.3 析构函数
析构函数的句法如下所示:
[特征 ] ~析构函数名 ()
{
代码
}
返回目录
19
常量( constance)是一个类的成员,它代表一个不变的数值,该数值在程序编译时可以被计算。
在 C#中,类的常量成员声明句法如下所示:
[特征 ] 常量修饰符 const 类型 常量声明符 ;
常量修饰符可以是 new,public,protected、
internal和 private等类型。
常量声明符为:常量成员标识符 =常量表达式
一条常量声明语句中可以同时声明多个常量 。
允许一个常量依赖同一个程序中的另一常量。
返回目录
20
字段( field)是类的一个成员,它表示的是与对象或类相关的一个变量。
字段的声明句法如下所示。
[特征 ] 字段修饰符 类型 字段声明符 ;
字段声明符如下:
标识符 =字段初始表达式
一条字段声明语句可以同时声明多个字段。
21
6.7.1 字段类别
1.实例字段和静态字段
实例字段和静态字段也称为实例变量和静态变量。
如果在声明字段时加上了 static修饰符,那么表明该字段是一个静态字段;否则,该字段就是一个实例字段。
静态字段与实例字段的最大区别就在于类的实例对字段的拷贝数目。
22
2.字段的访问
在程序中程序员可以直接利用字段名,或以成员访问的形式 E.M获得字段的数值。
如果一个字段以一个成员访问的形式( E.M)
引用时,如果 M是一个静态字段,那么 E必须指示的是一个类型;如果 M是一个实例字段,
那么 E必须指示的是一个实例。
23
6.7.2 只读字段
当一个字段声明时包括一个 readonly修饰符,
那么表明该字段是一个只读型的。
对于只读型字段来说,只能在该字段声明时,
或在其所属类的构造函数中为其分配数值。
1.为常量使用静态只读字段
2.常量和静态只读字段的版本问题
24
6.7.3 字段初始化
1.字段缺省值
如果字段在声明时未显示指定初始值,那么一个字段的初始值其实就是该字段声明时指定的类型的缺省值。
在程序中,当一个类被装载时,它的所有静态字段就被初始化为它们的缺省值;当类的一个实例被创建时,它的所有实例字段就被初始化为它们的缺省值。
25
2.字段初始化表达式
对一个静态字段来说,该初始化表达式对应于类被装载时将执行的那些赋值语句。
对实例字段来说,该初始化表达式对应于创建类的实例时将被执行的那些语句。
返回目录
26
运算符重载是指同名运算符可用于运算不同类型的数据。
在 C#中,不是所有的运算符都允许重载。
27
6.8.1 一元运算符重载
一元运算符 +,-,!,~ 必须使用类型 T的单个参数,但是可以返回任何类型。
一元运算符 ++,--必须使用类型 T的单个参数,
并且要返回类型 T。
一元运算符 true,false必须使用类型 T的单个参数,并且要返回类型 bool。
这里 T代表包含运算符声明的类或结构类型
28
6.8.2 二元运算符重载
一个二元运算符必须有两个参数,而且其中至少一个必须是声明运算符的类或结构的类型。一个二元运算符可以返回任何类型。
二元运算符的签名由运算符符号和两个形式参数组成。
某些二元运算符需要成对声明。
29
6.8.3 转换运算符
一个转换运算符声明定义了一个自定义转换。
关键字 implicit声明了一个用户自定义的隐式转换。
关键字 explicit声明了一个用户自定义的显式转换。
转换运算符的签名由源类型和目标类型组成 。
返回目录