继承
2015-10-20 13:40
239 查看
继承(加上封装和多态性)是面向对象的编程的三个主要特性(也称为“支柱”)之一。 继承用于创建可重用、扩展和修改在其他类中定义的行为的新类。 其成员被继承的类称为“基类”,继承这些成员的类称为“派生类”。 派生类只能有一个直接基类。 但是,继承是可传递的。 如果 ClassB 派生出 ClassC,ClassA 派生出 ClassB,则 ClassC 会继承 ClassB 和 ClassA 中声明的成员。
从概念上来说,派生类是基类的特例。 例如,如果您有一个基类 Animal,则可以有一个名为 Mammal 的派生类和一个名为 Reptile 的派生类。 Mammal 是一个 Animal,Reptile 也是一个 Animal,但每个派生类均表示基类的不同专用化。
定义一个类从其他类派生时,派生类隐式获得基类的除构造函数和析构函数以外的所有成员。 因此,派生类可以重用基类中的代码而无需重新实现这些代码。 可以在派生类中添加更多成员。 派生类以这种方式扩展基类的功能。
抽象方法和虚方法
当基类将方法声明为 virtual 时,派生类可以用自己的实现重写该方法。 如果基类将成员声明为 abstract,则在直接继承自该类的任何非抽象类中都必须重写该方法。 如果派生类自身是抽象的,则它继承抽象成员而不实现它们。 抽象成员和虚成员是多态性的基础,多态性是面向对象的编程的第二个主要特性。
抽象基类
如果希望禁止通过 new关键字直接进行实例化,可以将类声明为abstract 如果这样做,则仅当从该类派生新类时才能使用该类。 抽象类可以包含一个或多个自身声明为抽象的方法签名。 这些签名指定参数和返回值,但没有实现(方法体)。 抽象类不必包含抽象成员;但是,如果某个类确实包含抽象成员,则该类自身必须声明为抽象类。 自身不是抽象类的派生类必须为抽象基类中的任何抽象方法提供实现。
接口
“接口”是一种引用类型,有点像仅包含抽象成员的抽象基类。 类在从接口实现时必须为该接口的所有成员提供实现。类虽然只能从一个直接基类派生,但可以实现多个接口。
接口用于为不一定具有“是”关系的类定义特定功能。 例如,System.IEquatable 接口可由任何类或构造实现,这些类或构造必须启用代码来确定该类型的两个对象是否等效(但是该类型定义等效性)。 IEquatable 不表示基类和派生类之间存在的同一种“是”关系(例如 Mammal 是 Animal)。
派生类对基类的访问
派生类可以访问基类的公共成员、受保护成员、内部成员和受保护内部成员。 即使派生类继承基类的私有成员,仍不能访问这些成员。 但是,所有这些私有成员在派生类中仍然存在,且执行与基类自身中相同的工作。 例如,假定一个受保护基类方法访问私有字段。 要使继承的基类方法正常工作,派生类中必须有该字段。
禁止进一步派生
类可以将自身或其成员声明为 sealed,从而禁止其他类从该类自身或其任何成员继承。
派生类隐藏基类成员
派生类可以通过以相同的名称和签名声明基类成员来隐藏这些成员。 可以使用 new 修饰符显式指示成员不作为基类成员的重写。 不是必须要使用 new,但如果不使用 new,将生成编译器警告。
从概念上来说,派生类是基类的特例。 例如,如果您有一个基类 Animal,则可以有一个名为 Mammal 的派生类和一个名为 Reptile 的派生类。 Mammal 是一个 Animal,Reptile 也是一个 Animal,但每个派生类均表示基类的不同专用化。
定义一个类从其他类派生时,派生类隐式获得基类的除构造函数和析构函数以外的所有成员。 因此,派生类可以重用基类中的代码而无需重新实现这些代码。 可以在派生类中添加更多成员。 派生类以这种方式扩展基类的功能。
public class WorkItem { private static int currentID; protected int ID { get; set; } protected string Title { get; set; } protected string Description { get; set; } protected TimeSpan jobLength { get; set; } public WorkItem() { ID = 0; Title = "Default Title"; Description = "Default Description"; jobLength = new TimeSpan(); } static WorkItem() { currentID = 0; } protected int GetNextID() { return ++currentID; } public WorkItem(string title, string desc, TimeSpan ts) { this.ID = GetNextID(); this.Description = desc; this.Title = title; this.jobLength = ts; } public void Update(string title, TimeSpan ts) { this.Title = title; this.jobLength = ts; } public override string ToString() { return this.ID.ToString(); } } public class ChangeRequest : WorkItem { protected int originalItemID { get; set; } public ChangeRequest(){} public ChangeRequest(string title, string desc, TimeSpan ts, int oid) { this.ID = GetNextID(); this.Title = title; this.Description = desc; this.jobLength = ts; this.originalItemID = oid; } } class Program { static void Main(string[] args) { WorkItem wi0 = new WorkItem("title0","desc0",new TimeSpan(4,0,0)); Console.WriteLine(wi0.ToString()); WorkItem wi1 = new WorkItem("title0", "desc0", new TimeSpan(4, 0, 0)); Console.WriteLine(wi1.ToString()); ChangeRequest cr0 = new ChangeRequest("title0", "desc0", new TimeSpan(4, 0, 0), 0); Console.WriteLine(cr0.ToString()); Console.ReadKey(); } }
抽象方法和虚方法
当基类将方法声明为 virtual 时,派生类可以用自己的实现重写该方法。 如果基类将成员声明为 abstract,则在直接继承自该类的任何非抽象类中都必须重写该方法。 如果派生类自身是抽象的,则它继承抽象成员而不实现它们。 抽象成员和虚成员是多态性的基础,多态性是面向对象的编程的第二个主要特性。
抽象基类
如果希望禁止通过 new关键字直接进行实例化,可以将类声明为abstract 如果这样做,则仅当从该类派生新类时才能使用该类。 抽象类可以包含一个或多个自身声明为抽象的方法签名。 这些签名指定参数和返回值,但没有实现(方法体)。 抽象类不必包含抽象成员;但是,如果某个类确实包含抽象成员,则该类自身必须声明为抽象类。 自身不是抽象类的派生类必须为抽象基类中的任何抽象方法提供实现。
接口
“接口”是一种引用类型,有点像仅包含抽象成员的抽象基类。 类在从接口实现时必须为该接口的所有成员提供实现。类虽然只能从一个直接基类派生,但可以实现多个接口。
接口用于为不一定具有“是”关系的类定义特定功能。 例如,System.IEquatable 接口可由任何类或构造实现,这些类或构造必须启用代码来确定该类型的两个对象是否等效(但是该类型定义等效性)。 IEquatable 不表示基类和派生类之间存在的同一种“是”关系(例如 Mammal 是 Animal)。
派生类对基类的访问
派生类可以访问基类的公共成员、受保护成员、内部成员和受保护内部成员。 即使派生类继承基类的私有成员,仍不能访问这些成员。 但是,所有这些私有成员在派生类中仍然存在,且执行与基类自身中相同的工作。 例如,假定一个受保护基类方法访问私有字段。 要使继承的基类方法正常工作,派生类中必须有该字段。
禁止进一步派生
类可以将自身或其成员声明为 sealed,从而禁止其他类从该类自身或其任何成员继承。
派生类隐藏基类成员
派生类可以通过以相同的名称和签名声明基类成员来隐藏这些成员。 可以使用 new 修饰符显式指示成员不作为基类成员的重写。 不是必须要使用 new,但如果不使用 new,将生成编译器警告。
相关文章推荐
- PostgreSQL教程(三):表的继承和分区表详解
- Lua面向对象之类和继承浅析
- 浅析Ruby中继承和消息的相关知识
- 设计引导--一个鸭子游戏引发的设计理念(多态,继承,抽象,接口,策略者模式)
- C++实现不能被继承的类实例分析
- PHP类的封装与继承详解
- js继承 Base类的源码解析
- Javascript 面向对象 继承
- JavaScript 继承使用分析
- Javascript面向对象编程(二) 构造函数的继承
- javascript面向对象之Javascript 继承
- JavaScript 对象、函数和继承
- 关于JavaScript的面向对象和继承有利新手学习
- JavaScript 继承详解(一)
- JavaScript 继承详解(二)
- javascript继承的六大模式小结
- JavaScript中的原型和继承详解(图文)
- JavaScript中继承用法实例分析
- Javascript中3种实现继承的方法和代码实例
- 通过继承IHttpHandle实现JS插件的组织与管理