什么是继承?
面向对象编程(OOP)中的继承是一种机制,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。继承是OOP的三大基本特性之一,另外两个是封装和多态。
继承是面向对象的编程的一种基本特性。 借助继承,能够定义可重用(继承)、扩展或修改父类行为的子类。 成员被继承的类称为基类。 继承基类成员的类称为派生类。
C#继承是指对C#语言中现有类(基类、父类)上建立新类(派生类、子类)的处理过程。
在现有类(基类、父类)上建立新类(派生类、子类)的处理过程称为继承。派生类能自动获得基类的除了构造函数和析构函数以外的所有成员,可以在派生类中添加新的属性和方法扩展其功能。
继承是软件复用的一种形式。使用继承可以复用现有类的数据和行为,为其赋予新功能而创建出新类。
C# 和 .NET 只支持单一继承。 也就是说,类只能继承自一个类。 不过,继承是可传递的。这样一来,就可以为一组类型定义继承层次结构。
换言之,类型 D 可继承自类型 C,其中类型 C 继承自类型 B,类型 B 又继承自基类类型 A。 由于继承是可传递的,因此类型 D
继承了类型 A 的成员。并非所有基类成员都可供派生类继承。 以下成员无法继承:
静态构造函数:用于初始化类的静态数据。
实例构造函数:在创建类的新实例时调用。 每个类都必须定义自己的构造函数。
终结器:由运行时的垃圾回收器调用,用于销毁类实例。
虽然基类的其他所有成员都可供派生类继承,但这些成员是否可见取决于它们的可访问性。 成员的可访问性决定了其是否在派生类中可见,如下所述:
只有在基类中嵌套的派生类中,私有成员才可见。 否则,此类成员在派生类中不可见。 在以下示例中,A.B 是派生自 A 的嵌套类,而 C
则派生自 A。 私有 A._value 字段在 A.B 中可见。不过,如果从 C.GetValue
方法中删除注释并尝试编译示例,则会生成编译器错误 CS0122:““A._value” 不可访问,因为它具有一定的保护级别。”[微软官方文档]
特征与作用
代码复用:继承可以减少代码重复,提高开发效率。子类可以继承父类的代码,而无需重新编写相同的功能。
层次结构:继承允许创建类之间的层次结构。一个父类可以有多个子类,这些子类可以共享父类的特性。
扩展性:子类可以扩展或修改父类的行为。它们可以添加新的属性和方法,或者重写(Override)父类的方法以改变其行为。
多态性:继承支持多态性,即同一个接口可以有多个实现。这意味着一个父类类型的引用可以指向子类的对象,并且可以调用子类特有的方法。
基类和派生类
一个类可以继承自另一个类,其中被继承的类被称作基类(父类),继承类被称作派生类(子类)。
C# 不支持类的多重继承,但支持接口的多重继承,一个类可以实现多个接口。
从概念上讲,派生类是基类的专门化。 例如,如果有一个基类 Animal,则可以有一个名为 Mammal 的派生类,以及另一个名为 Reptile 的派生类。 Mammal 是 Animal,Reptile 也是 Animal,但每个派生类表示基类的不同专门化。
概括来说:一个类可以继承多个接口,但只能继承自一个类。
<访问修饰符> class <基类>
{
...
}
class <派生类> : <基类>
{
...
}
代码实例
- 我们尝试写一个动物类的代码来实现一下继承的过程。
- 我们定义一个动物类(Animal),再定义一个个体类(Individual)来继承动物类的属性,创建一个猫(Cat)方法,在Cat中可以直接使用被被继承的Animal属性。(在使用使用被继承的属性事,我们需要先实例化Cat方法)
3.运行代码,可以看到,在没有调用的Animal的前提下,继承可以让我们直接使用Animal内的属性,我们可以理解为Animal中的属性,被复制到了派生类中了。
using System;
namespace Almango
{
public class Animal // 动物类
{
public string category; // 定义种类
public int Aggressiveness; // 定义攻击性
public int life; // 定义寿命
}
public class Individual() : Animal // 继承动物类
{
public void Cat() // 定义猫属性
{
Individual Cat = new Individual(); // 实例化猫
///
///将继承的属性调用
///
string a = Cat.category = "猫科动物";
int b = Cat.Aggressiveness = 10;
int c = Cat.life = 10;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
}
static void Main(string[] args)
{
Individual Cats = new Individual();
Cats.Cat();
}
}
}
运行结果
>猫科动物
>10
>10
继承的优点
C#中的继承提供了多种好处,这些好处有助于提高代码的可维护性、可扩展性和复用性。以下是C#继承的一些主要优点:
代码复用:继承允许子类继承父类的属性和方法,这意味着开发者可以避免重复编写相同的代码。这不仅减少了开发时间,还减少了出错的可能性。
减少代码冗余:通过继承,公共的功能可以放在父类中,而子类只需要实现或重写特定的功能。这有助于减少代码的冗余,使代码库更加简洁。
层次结构的建立:继承支持创建清晰的类层次结构,这有助于组织和管理大型软件项目。层次结构使得代码更加模块化,易于理解和维护。
扩展现有功能:子类可以扩展父类的功能,添加新的属性和方法,或者通过重写现有方法来改变行为。这为现有代码提供了灵活性,使其能够适应新的需求。
多态性的支持:继承是多态性的基础。多态性允许将子类的对象视为父类的对象,使得同一个接口可以有多种实现。这使得代码更加灵活,能够以统一的方式处理不同类型的对象。
设计模式的应用:继承是许多设计模式的关键组成部分,如工厂模式、建造者模式和策略模式等。这些模式可以解决特定的设计问题,提高代码的可重用性和灵活性。
简化单元测试:由于子类继承了父类的行为,因此在进行单元测试时,可以专注于测试子类特有的行为,而不必重新测试父类已经验证过的行为。
提高代码的可读性:当代码遵循良好的继承结构时,其他开发者可以更容易地理解代码的工作原理,因为类之间的关系清晰明确。
有助于实现封装:继承可以促进封装的实现,因为子类可以继承父类的私有成员,同时提供公共的接口来访问这些成员。
促进面向接口编程:虽然继承本身并不是接口,但它鼓励开发者考虑类之间的共同点,从而促进面向接口编程,这是一种更加灵活和可维护的编程风格。
尽管继承提供了许多好处,但开发者也应该意识到继承可能带来的问题,如过度继承、脆弱的基类问题和菱形继承问题等。合理使用继承,并结合其他OOP原则和设计模式,可以最大化继承的好处,同时避免潜在的问题。