📜  C#-继承(1)

📅  最后修改于: 2023-12-03 15:14:27.303000             🧑  作者: Mango

C# - 继承

继承是C#中面向对象编程中的一个核心概念,它允许我们提取共同的特征并将其放置在父类中,子类继承父类并获得这些特征,同时还可以添加自己的特征。这使得代码重复性减少,可读性更好,可维护性更强。

基本语法

在C#中,我们使用:运算符来实现继承。下面是一个简单的例子:

class Animal {
    public void Eat(string food) {
        Console.WriteLine($"I'm eating {food}!");
    }
}

class Cat : Animal {
    public void Meow() {
        Console.WriteLine("Meow!");
    }
}

Cat mimi = new Cat();
mimi.Eat("fish"); // 输出 "I'm eating fish!"
mimi.Meow();      // 输出 "Meow!"

在这个例子中,我们定义了一个Animal类,它有一个Eat方法。我们定义了一个Cat类,它继承自Animal类,并且除了继承自Animal类的Eat方法之外,还有自己的Meow方法。在我们创建了Cat的实例之后,我们可以调用其从Animal继承下来的Eat方法,也可以调用其自己的Meow方法。

值得注意的是,子类可以访问其父类的公有成员,但不能访问私有成员。

重写

有时,子类可能需要覆盖其父类中的某个方法,以改变其行为。我们可以使用override关键字来完成这个任务。下面是一个带有重写的例子:

class Animal {
    public virtual void MakeSound() {
        Console.WriteLine("I don't know how to make a sound.");
    }
}

class Cat : Animal {
    public override void MakeSound() {
        Console.WriteLine("Meow!");
    }
}

class Dog : Animal {
    public override void MakeSound() {
        Console.WriteLine("Woof!");
    }
}

Animal animal1 = new Animal();
Animal animal2 = new Cat();
Animal animal3 = new Dog();
animal1.MakeSound(); // 输出 "I don't know how to make a sound."
animal2.MakeSound(); // 输出 "Meow!"
animal3.MakeSound(); // 输出 "Woof!"

在这个例子中,我们定义了一个Animal类,它有一个虚拟方法MakeSound。同时,我们定义了两个子类CatDog,它们都重写了Animal类中的MakeSound方法。在我们创建了三个不同的实例之后,我们调用它们各自的MakeSound方法,得到了不同的结果。

值得注意的是,当使用virtual关键字修饰方法时,表示这个方法可以被子类重写。而当子类使用override关键字重写父类的虚拟方法时,也必须使用virtual关键字来修饰父类虚拟方法。

抽象类和接口

除了普通的类外,C#中还存在抽象类和接口两种特殊的类类型,它们都可以用于继承或者实现,在面向对象编程中发挥着重要的作用。

抽象类

抽象类是不能直接实例化的类,它只能用于被继承。与普通类不同的是,抽象类可以包含抽象方法,抽象方法必须被子类重写才能被运行。下面是一个抽象类的例子:

abstract class Animal {
    public abstract void MakeSound();
}

class Cat : Animal {
    public override void MakeSound() {
        Console.WriteLine("Meow!");
    }
}

class Dog : Animal {
    public override void MakeSound() {
        Console.WriteLine("Woof!");
    }
}

Animal animal1 = new Cat();
Animal animal2 = new Dog();
animal1.MakeSound(); // 输出 "Meow!"
animal2.MakeSound(); // 输出 "Woof!"

在这个例子中,我们定义了一个抽象类Animal和两个子类CatDog。由于Animal包含一个抽象方法MakeSound,所以Animal类本身不能被实例化。我们使用子类来实例化Animal,并且通过调用MakeSound方法来演示抽象方法的使用。

接口

与抽象类相似,接口也不能直接实例化。接口是一种特殊的类类型,它声明了一组公共方法、属性、索引器和事件,并没有实现。它的作用是定义了一组协议,使得其他类可以按照这个协议进行实现。下面是一个接口的例子:

interface IAnimal {
    void MakeSound();
}

class Cat : IAnimal {
    public void MakeSound() {
        Console.WriteLine("Meow!");
    }
}

class Dog : IAnimal {
    public void MakeSound() {
        Console.WriteLine("Woof!");
    }
}

IAnimal animal1 = new Cat();
IAnimal animal2 = new Dog();
animal1.MakeSound(); // 输出 "Meow!"
animal2.MakeSound(); // 输出 "Woof!"

在这个例子中,我们定义了一个接口IAnimal和两个子类CatDog。由于CatDog都实现了IAnimal接口中的MakeSound方法,所以它们可以被当做IAnimal类型来实例化。我们使用接口来实现多态,即使子类的实现方式不同,但它们都遵循了IAnimal接口的协议,具有了相同的行为。

总结

继承是C#中面向对象编程的核心概念之一,它允许我们重用代码、减少重复、提高可读性和可维护性。在使用继承时,我们通常需要了解基本的语法和相关的概念,如重写、抽象类和接口等,以充分发挥继承的优势。