第10章 类
类是面向对象的程序设计的基本构成模块。
-从定义上讲,类是一种数据结构,这种数据结构可能包含数据成员、函数成员以及其它的嵌套类型。其中数据成员类型有 常量、域和事件;;
-函数成员类型有: 方法、属性、索引指示器、操作符、构造函数和析构函数。
10.1 类的声明
eg. attributes class-modifiers class identifier class-base class-body ;
eg. [可选属性] [修饰符 pulic] [关键字class] [类名] [继承方式] [基类名]
- 类的修饰符
-类的修饰符可以是以下几种之一或者是它们的组合(在类的声明中同一修饰符不允许出现多次);
- new ——仅允许在嵌套类声明时使用,表明类中隐藏了由基类中继承而来的、与基类中同名的成员。
- public ——表示不限制对类的访问。
- protected ——表示只能从所在类和所在类派生的子类进行访问。
- internal ——只有其所在类才能访问。
- private ——只有对包.Net中的应用程序或库才能访问。
- abstract ——抽象类,不允许建立类的实例。
- sealed ——密封类,不允许被继承。
-
new 类的实例化,
class A{}
calss B
{
A a = new A();
} -
类的继承
class A{}
class B:A{}
10.2 类的成员
类的成员可以分为两大类: 类本身所声明的,以及从基类中继承来的。
- 类成员有以下类型
- 成员常量——代表与相关联的常量值。
- 域,——即类中的变量。
- 成员方法,——复杂执行类中的计算和其它操作。
- 属性,——用于定义类中的值,并对他们进行读写。
- 事件,——用于说明发生了什么事情。
- 索引指示器,——允许像使用数组那样为类添加路径列表。
- 操作符,——定义类中特有的操作。
- 构造函数 和析构函数,——分别用于对类的实例进行初始化和销毁。
10.2.1 对类的成员的访问
- 公有成员 ——Public 允许类的使用者从外部进行访问。公有成员的修饰符为 public ,这是限制最少的一种访问方式。
- 私有成员 ——private 仅限于类中的成员可以访问,从类的外部访问私有成员是不合法的。[如果再声明中没有出现访问修饰符,按照默认方式为 私有的。private]
- 保护成员 ——protected 为了方便派生类的访问,有希望成员对外界是隐藏的。
- 内部成员 —— 类的成员是一种特殊的成员。这种成员对于同一包中应用程序或库是透明的,而在包.Net之外是禁止访问的。
10.2.2 this 保留字
- 保留字 this 仅限于在构造函数、类的方法和类的实例中使用,它有以下含义:
- 在中类***的构造函数中*出现的 this 作为一个值类型,它表示 对正在构造的对象本身的引用。
- 在类的***方法中*出现的 this作为一个值类型,它表示对调用该方法的对象的引用。
- 在***结构的构造函数***中出现的this作为一个***变量类型***,他表示对正在构造的机构的引用。
- 在 结构的方法 ** 中出现的this 作为一个变量类型**,他表示对调用该方法的结构的引用。
除此以外,在其它地方使用this 保留字都是不合法的。
10.2.3 静态成员和非静态成员
若将类中的某个成员声明为static,该成员成为静态成员。类中的成员要么是静态,要么是非静态的。————一般说来,静态成员是属于类所有的,非静态成员则属于类的实例 对象。
以下示例代码演示了如何声明静态和非静态成员。
using System;
class Test
{
int x;
static int y;
void F()
{
x = 1; // 正确,等价于this.x = 1
y = 1; // 正确,等价于Test.y = 1
}
static void G()
{
x = 1; // 错误不能访问 this.x
y = 1; // 正确,等价于Test.y = 1
}
static void Main()
{
Test t = new Test();
t.x = 1; // 正确
t.y = 1; // 错误不能在类的实例中访问静态成员
Test.x = 1; // 错误不能按类访问非静态成员
Test.y = 1; // 正确
}
}
> - 类的非静态成员属于类的实例所有,没创建一个类的实例,都在内存中为非静态成员开辟了一块区域。而类的静态成员属于类所有,为这个类的所有实例所共享。无论这个类创建了多少个副本,一个静态成员在内存中之占有一块区域。
10.2.4 成员常量
让我们再看一个成员常量的声明例子
class A
{
public const double X = 1.0;
public const double Y = 2.0;
public const double Z = 3.0;
}
关键字const 用于声明常量,后跟数据类型的声明。类的常量可以加上以下修饰符:
new、 public、private、protected、internal 可以用一条语句同时声明多个常量,比如上例我们可以写成:
class A
{
publice const double X = 1.0,Y = 2.0, Z = 3.0;
}
10.3 构造函数 和析构函数
10.3.1 构造函数
-构造函数用于执行类的实例的初始化。每个类都有构造函数,即使我们没有声明它,编译器也会自动地为我们提供一个默认的构造函数。;;;在访问一个类的时候,系统将最先执行构造函数中的语句。实际上,任何构造函数的执行都隐式地调用了系统提供的默认的构造函数base().
- 一个类的构造函数通常与类名相同。
- 构造函数不声明返回类型。
- 一般地,构造函数总是Public类型的。如果是private 类型的,表明类不能被实例化,同创用于只含有静态成员的类。
- 在构造函数中不要做对类的实例进行初始化以外的事情,也不要尝试显式地调用构造函数。
class A
{
int x = 0, y = 0, count;
public A()
{
count = 0;
}
public A(int vx,int vy)
{
x = vx;
y = vy;
}
}
10.3.2 构造函数的参数
程序清单10-6
using System;
class Vehicle//定义汽车类
{
public int wheels; //公有成员轮子个数
protected float weight; //保护成员重量
public Vehicle(){;}
public Vehicle(int w,float g)
{
wheels = w;
weight = g;
}
public void Show()
{
Console.WriteLine(“the wheel of vehicle is:{0}”,wheels);
Console.WriteLine(“the weight of vehicle is:{0}”,weight);
}
};
class train //定义火车类
{
public int num; //公有成员车厢数目
private int passengers; //私有成员乘客数
private float weight; //私有成员重量
public Train(){;}
public Train(int n,int p,float w)
{
num = n;
passengers = p;
weight = w;
}
public void Show()
{
Console.WriteLine(“the num of train is:{0}”,num);
Console.WriteLine(“the weight of train is:{0}”,weight);
Console.WriteLine(“the Passengers train car is:{0}”, Passengers);
}
}
class Car:Vehicle //定义轿车类
{
int passengers; //私有成员乘客数
public Car(int w,float g,int p) : base(w,g)
{
wheels = w;
weight = g;
passengers = p;
}
new public void Show()
{
Console.WriteLine(“the wheel of car is:{0}”,wheels);
Console.WriteLine(“the weight of car is:{0}”,weight);
Console.WriteLine(“the Passengers of car is:{0}”, Passengers);
}
}
class Test
{
public static void Main()
{
Vehicle v1 = new Vehicle(4,5);
Train t1 = new Train();
Train t2 = new Train(10,100,100);
Car c1 = new Car(4,2,4);
v1.show();
t1.show();
t2.show();
c1.show();
}
}
10.3.3 析构函数
析构函数的名字与类名相同,只是在前面加了一个符号“~”。析构函数不接受任何参数,也不返回任何值。C#中提供了析构函数,用于专门释放被占用的系统资源。
10.4 小结
- 学习了C#中类的基本概念,展示了类的各种组成。
C# 中的类是对数据结构的封装与抽象,是 c#最重要的组成部分。 我们利用类定义各种新的数据类型,其中即包含数据内容,又包含对数据内容的操作。封装之后,类可以控制外界对它的成员的访问。
- 类的静态成员属于该类,非静态成员则属于这个类的某个实例。
- 在一个类的实例——对象的声明周期中,最先执行的代码就是类的构造函数。构造函数是用来初始化对象的特殊类型的函数。
- 不带参数的构造函数对垒的实例的初始化是固定的。我们也可以使用带参数的构造函数,通过向它传递参数来对类的不同实例进行不同的初始化。构造函数同样可以使用默认参数。
- 当这个类的实例超出作用域时,或者由于其它理由被破坏时,析构函数将释放分配给该实例的任何存储区。