首页 > 编程笔记 > C#笔记 阅读:11

C#继承用法详解(附带实例)

C# 面向对象的程序设计中,类是可以继承(inheritance)的,其中被继承的类称为父类(parent class)、超类(superclass)或基类(base class),继承的类称为子类(child class或subclass)或衍生类(derived class)。

类继承的最大优点是许多父类的字段、属性与方法,在子类中不用重新设计,可以直接引用,另外子类也可以有自己的字段、属性与方法。

从3个简单的C#程序谈起

【实例 1】这是一个 Animal 动物类,这个类的字段是 name,代表动物的名字。然后有两个方法,分别是 Eat() 和 Sleep(),这两个方法会分别列出“name正在吃食物”和“name正在睡觉”。
Animal animal = new Animal("Lily");
animal.Eat();
animal.Sleep();

public class Animal
{
    string name;
    public Animal (string name) => this.name = name;
    public void Eat()
    {
        Console.WriteLine($"{name} 正在吃食物");
    }
    public void Sleep()
    {
        Console.WriteLine($"{name} 正在睡觉");
    }
}
执行结果为:

Lily 正在吃食物
Lily 正在睡觉


【实例 2】这是一个 Dog 类,这个类的字段是 name,代表动物的名字。然后有 3 个方法,分别是 Eat()、Sleep() 和 Barking(),这 3 个方法会分别列出“name正在吃食物”、“name正在睡觉”和“name正在叫”。
Dog dog = new Dog("Haly");
dog.Eat();
dog.Sleep();
dog.Barking();

public class Dog
{
    string name;
    public Dog(string name) => this.name = name;
    public void Eat()
    {
        Console.WriteLine($"{name} 正在吃食物");
    }
    public void Sleep()
    {
        Console.WriteLine($"{name} 正在睡觉");
    }
    public void Barking()
    {
        Console.WriteLine($"{name} 正在叫");
    }
}
执行结果为:

Haly 正在吃食物
Haly 正在睡觉
Haly 正在叫


【实例 3】这是一个 Bird(鸟)类,这个类的字段是 name,代表动物的名字。然后有 3 个方法,分别是 Eat()、Sleep() 和 Flying(),这 3 个方法会分别列出“name正在吃食物”、“name正在睡觉”和“name正在飞”。
Bird bird = new Bird("CiCi");
bird.Eat();
bird.Sleep();
bird.Flying();

public class Bird
{
    string name;
    public Bird(string name) => this.name = name;
    public void Eat()
    {
        Console.WriteLine($"{name} 正在吃食物");
    }
    public void Sleep()
    {
        Console.WriteLine($"{name} 正在睡觉");
    }
    public void Flying()
    {
        Console.WriteLine($"{name} 正在飞");
    }
}
执行结果为:

CiCi 正在吃食物
CiCi 正在睡觉
CiCi 正在飞

我们可以使用下图,列出上述 3 个主要类的成员变量与方法:


其实狗和鸟都是动物,由上图关系可以看出 Dog 类、Bird 类与 Animal 类都有相同的字段 name,同时有相同的方法 Eat() 和 Sleep(),然后 Dog 类有属于自己的方法 Barking(),Bird 类有属于自己的方法 Flying()。

如果我们将上述 3 个程序写成一个程序,则将创造一个冗长的程序代码,可是如果我们利用 C# 面向对象的继承(inheritance)概念,整个程序将简化许多。

C#继承的语法

C# 的继承需使用关键词符号“:”,语法如下:
存取修饰词 class 子类名称 : 父类名称
{
    // 子类字段、属性与方法
}

若是从 Animal 类和 Dog 类的关系看,Animal 类是 Dog 类的父类,或者 Dog 类是 Animal 类的子类,Dog 类可以继承 Animal 类,可以用下列方式设计 Dog 类。
public class Dog : Animal
{
    // Dog类字段、属性与方法
}

【实例 4】将实例 1 和实例 2 做简化省略属性,组成一个程序,以体会子类 Dog 继承父类 Animal 的方法。
Dog dog = new Dog();
dog.Eat();
dog.Sleep();
dog.Barking();

public class Animal
{
    public void Eat()
    {
        Console.WriteLine("正在吃食物");
    }
    public void Sleep()
    {
        Console.WriteLine("正在睡觉");
    }
}

public class Dog : Animal
{
    public void Barking()
    {
        Console.WriteLine("正在叫");
    }
}
执行结果为:

正在吃食物
正在睡觉
正在叫

上述程序中由于 Dog 类继承了 Animal 类,所以 dog 对象可以正常使用父类 Animal 的 eat() 和 sleep() 方法,这样 Dog 类就可以省略 Eat() 和 Sleep() 方法,达到重用程序代码、精简程序的目的也减少错误发生,下列是上述程序的说明图。


上述实例中,Dog 类继承了 Animal 类,我们可以称为单一继承。

C#构造方法的调用

正常的类一定有字段,当我们声明创建子类对象时,可以利用子类本身的构造方法初始化自己的字段。至于子类所继承的父类字段,则由父类自身的构造方法初始化其本身的字段。

其实我们创建一个子类的对象时,C# 在调用子类的构造方法前会先调用父类的构造方法。其实这个概念很简单,子类继承了父类的内容,所以子类在创建本身的对象前,一定要先初始化所继承的父类的内容,下列程序实例将验证这个概念。

【实例 5】创建一个 Dog 类的对象,观察在调用其本身的构造方法前,父类 Animal 的构造方法会先被调用。
Dog dog = new Dog();
dog.Eat();
dog.Sleep();
dog.Barking();

public class Animal
{
    public Animal() => Console.WriteLine("执行Animal构造方法 ...");
    public void Eat()
    {
        Console.WriteLine("正在吃食物");
    }
    public void Sleep()
    {
        Console.WriteLine("正在睡觉");
    }
}

public class Dog : Animal
{
    public Dog() => Console.WriteLine("执行Dog构造方法 ...");
    public void Barking()
    {
        Console.WriteLine("正在叫");
    }
}
执行结果为:

执行Animal构造方法 ...
执行Dog构造方法 ...
正在吃食物
正在睡觉
正在叫

上述程序在第 2 行声明 Dog 类的 dog 对象时,会先调用父类的构造方法,所以输出第一行字符串“执行Animal构造方法…”,然后输出第二行字符串“执行Dog构造方法…”。

C#父类属性为public时子类初始化父类属性

现在我们扩充方案实例 5,扩充父类的属性 name,同时将 name 声明为 public,由于子类可以继承父类的所有 public 属性,所以这时可以由子类的构造方法初始化父类的属性 name。

【实例 6】这个程序基本上是组合了实例 1 和实例 2,但是将父类 Animal 的属性 name 声明为 public。
Dog dog = new Dog("Haly");
dog.Eat();
dog.Sleep();
dog.Barking();

public class Animal
{
    public string name;
    public void Eat()
    {
        Console.WriteLine($"{name} 正在吃食物");
    }
    public void Sleep()
    {
        Console.WriteLine($"{name} 正在睡觉");
    }
}

public class Dog : Animal
{
    public Dog(string name)
    {
        this.name = name; // 构造方法使用父类的name属性
    }
    public void Barking()
    {
        Console.WriteLine($"{name} 正在叫");
    }
}
执行结果为:

Haly 正在吃食物
Haly 正在睡觉
Haly 正在叫

相关文章