导入
继承
本课程详细讨论了继承,以及派生类和基类中的构造函数。
什么是继承
-
提供了一种从现有类创建新类的方式。
-
新类是现有类的特殊化版本。
-
允许新类重用来自现有类的方法。
术语
- 基类(或父类):被子类继承。
- 派生类(或子类):从基类继承。
特性
一个派生类具有:
- 派生类中定义的所有成员。
- 基类中声明的所有成员。
一个派生类可以:
- 使用在派生类中定义的所有
public成员。 - 使用在基类中定义的所有
public成员。 - 重写一个继承的成员。
一个派生类不能:
- 继承构造函数和析构函数。
- 改变继承成员的定义。
表示法
让我们看一下这两种类型的表示法。
1class Student { // 基类 2 // 内容 3} 4 5// 派生类通过使用 : 操作符从另一个类继承 6class UnderGrad : Student { 7 // 内容 8}
示例
考虑一个包含基类 Shape 和派生类 Square 的例子。
1using System; 2 3// 基类 4class Shape { 5 public Shape() { length = 0; } // 默认构造函数 6 public void setlength(int l) { length = l; } 7 protected int length; 8} 9 10// 派生类 11class Square : Shape { 12 public Square() { length = 0; } // 声明并初始化派生类构造函数 13 public int get_Area() { return (length * length); } 14} 15 16class Program 17{ 18 static void Main() 19 { 20 Square sq = new Square(); // 创建子类 Square 的对象 21 sq.setlength(5); // 将长度设置为 5 22 // 输出对象的面积 23 Console.WriteLine("正方形的总面积是: {0}", sq.get_Area()); 24 } 25}
如上例所示:
Shape类是父类,而Square类是子类,它从Shape类派生而来。- 在我们的子类
Square中,我们使用了父类的成员,例如:protected的length变量,在默认构造函数中被初始化为 零。length也在子类的get_Area函数中被用于计算正方形的面积。
- 在
Main方法中,setlength函数作为父类的public成员函数,对子类对象sq是可访问的。- 使用点号操作符来访问
Main中的setlength。
- 使用点号操作符来访问
构造函数
当创建 Square 类的实例时,如果没有显式调用父类中的其他构造函数,则会自动调用基类的默认构造函数(无参数)。
在本例中,首先调用 Shape 类的构造函数,然后调用 Square 类的构造函数。
在上述示例中,Square 类的构造函数调用了 Shape 类的默认构造函数。如果你愿意,也可以指定要调用哪个构造函数:可以使用 base 关键字调用父类中任何已定义的构造函数。
示例
为了更好地理解,请看下面的例子。
1using System; 2 3class Shape { 4 protected int length; 5 public Shape() { // 默认构造函数 6 Console.WriteLine("Shape 的默认构造函数"); 7 } 8 public Shape(int length) { // 带参数的构造函数 9 this.length = length; 10 Console.WriteLine("Shape 的带一个参数的构造函数"); 11 Console.WriteLine(this.length); 12 } 13} 14 15class Square : Shape { 16 public Square() : base() { // 使用 base 调用 Shape 类的默认构造函数 17 Console.WriteLine("Square 的默认构造函数"); 18 } 19 public Square(int length) : base(length) { // 使用 base 调用 Shape 类的带参数构造函数 20 Console.WriteLine("Square 的带一个参数的构造函数"); 21 Console.WriteLine(this.length); 22 } 23 public int get_Area() { return (length * length); } // 计算正方形面积的方法 24} 25 26class Program { 27 static void Main() { 28 Square sq1 = new Square(); // 创建子类 Square 的对象 29 Square sq2 = new Square(5); // 将长度设置为 5 30 Console.WriteLine("sq1 的面积是: {0}", sq1.get_Area()); 31 Console.WriteLine("sq2 的面积是: {0}", sq2.get_Area()); 32 } 33}
在上面的代码中:
-
每个类都有两个构造函数。
-
我们使用了
base关键字,它是对父类的引用。 -
在本例中,当我们创建
Square类的实例时(第 28 行):- 运行时首先调用
Square(),即无参数的构造函数。但其主体并不会立即执行。 - 在构造函数的括号之后,有一个
base()调用,这意味着当我们调用Square的默认构造函数时,它会进一步调用父类的默认构造函数。 - 父类构造函数执行完毕后返回,然后才执行
Square()构造函数的主体。
- 运行时首先调用
-
父类中非
private的成员会被子类继承,这意味着Square类也拥有length字段。- 在这种情况下,第 29 行我们向构造函数传递了一个参数。
- 它将该参数传递给父类的带参数构造函数,从而初始化
length字段。
到目前为止有趣吗?在下一课中,我们将讨论多态性和虚方法。继续阅读以了解更多内容!