更新: 2008 年 7 月
继承(加上封装和多态性)是面向对象的编程的三个主要特性(“支柱”)之一。继承用于创建可重用、扩展和修改在其他类中定义的行为的新类。其成员被继承的类称为“基类”,继承这些成员的类称为“派生类”。
说明: |
---|
结构不支持继承,但可以实现接口。有关更多信息,请参见接口(C# 编程指南)。 |
从概念上来说,派生类是基类的专用化。例如,如果您有一个基类 Animal,则可以有一个名为 Mammal 的派生类和一个名为 Reptile 的派生类。Mammal 是一个 Animal,Reptile 也是一个 Animal,但每个派生类均表示基类的不同专用化。
定义一个类从其他类派生时,派生类隐式获得基类的除构造函数和析构函数以外的所有成员。因此,派生类可以重用基类中的代码而无需重新实现这些代码。可以在派生类中添加更多成员。派生类以这种方式扩展基类的功能。
下图演示一个 WorkItem 类,该类表示某业务流程中的一个工作项。和所有的类一样,该类派生自
下面的示例演示如何以 C# 表示上图所示的类关系。该示例还演示 WorkItem 如何重写虚方法
C# | 复制代码 |
---|---|
// WorkItem implicitly inherits from Object class public class WorkItem { private static int nextID; protected int ID { get; set; } protected TimeSpan jobLength { get; set; } protected string Title { get; set; } protected string Description { get; set; } // Default constructor public WorkItem() { ID = 0; Title = "Default title"; Description = "Default description."; jobLength = new TimeSpan(); } // Static constructor for static member. static WorkItem() { nextID = 0; } // Instance constructor. public WorkItem( string title, string desc, TimeSpan joblen) { this.ID = GetNextID(); this.Title = title; this.Description = desc; this.jobLength = joblen; } protected int GetNextID() { return ++nextID; } public void Update(string title, TimeSpan joblen) { this.Title = title; this.jobLength = joblen; } // Virtual method override. public override string ToString() { return String.Format("{0} - {1}", this.ID, this.Title); } } // ChangeRequest derives from WorkItem and adds two of its own members. public class ChangeRequest : WorkItem { protected int originalItemID {get; set;} public ChangeRequest() { } public ChangeRequest(string title, string desc, TimeSpan jobLen, int originalID) { this.ID = GetNextID(); this.Title = title; this.Description = desc; this.jobLength = jobLen; this.originalItemID = originalID; } } class Program { static void Main() { WorkItem item = new WorkItem( "Fix Bugs", "Fix all bugs in my source code branch", new TimeSpan(3, 4, 0, 0)); ChangeRequest change = new ChangeRequest("Change design of base class", "Add members to base class", new TimeSpan(4, 0, 0), 1); Console.WriteLine(item.ToString()); // ChangeRequest inherits WorkItem's override of ToString Console.WriteLine(change.ToString()); // Keep the console open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } } /* Output: 1 - Fix Bugs 2 - Change design of base class */ |
抽象方法和虚方法
当基类将方法声明为
抽象基类
如果希望禁止通过
接口
“接口”是一种引用类型,有点像仅包含抽象成员的抽象基类。类在从接口派生时必须为该接口的所有成员提供实现。类虽然只能从一个直接基类派生,但可以实现多个接口。
接口用于为不一定具有“是”关系的类定义特定功能。例如,如果任何类或结构需要让客户端代码判断某类型的两个对象是否相等(无论该类型如何定义相等性),那么该类或结构就可以实现 IEquatable[`1] 接口。
派生类对基类成员的访问
派生类可以访问基类的公共成员、受保护成员、内部成员和受保护内部成员。即使派生类继承基类的私有成员,仍不能访问这些成员。但是,所有这些私有成员在派生类中仍然存在,且执行与基类自身中相同的工作。例如,假定一个受保护基类方法访问私有字段。要使继承的基类方法正常工作,派生类中必须有该字段。
禁止进一步派生
类可以将自身或其成员声明为
派生类隐藏基类成员
派生类可以通过以相同的名称和签名声明基类成员来隐藏这些成员。可以使用
请参见
修订记录
日期 | 修订记录 | 原因 |
---|---|---|
2008 年 7 月 | 增加了内容、图示和新示例。 |
信息补充。 |