C#学习入门概念之二(面向对象编程三个特征之继承)
2016-11-26 21:20
519 查看
继承(加上封装和多形性)是面向对象的编程的三个主要特性(也称为“支柱”)之一。 继承用于创建可重用、扩展和修改在其他类中定义的行为的新类。
其成员被继承的类称为“基类”,继承这些成员的类称为“派生类”。 派生类只能有一个直接基类。 但是,继承是可传递的。 如果 ClassB
派生出 ClassC,ClassA 派生出 ClassB,则 ClassC 会继承 ClassB 和 ClassA 中声明的成员。
结构不支持继承,但可以实现接口。 有关更多信息,请参见 接口。
从概念上来说,派生类是基类的专用化。 例如,如果您有一个基类
定义一个类从其他类派生时,派生类隐式获得基类的除构造函数和析构函数以外的所有成员。 因此,派生类可以重用基类中的代码而无需重新实现这些代码。 可以在派生类中添加更多成员。 派生类以这种方式扩展基类的功能。
下图演示一个
下面的示例演示如何以 C# 表示上图所示的类关系。 该示例还演示
当基类将方法声明为 virtual 时,派生类可以用自己的实现重写该方法。 如果基类将成员声明为 abstract,则在直接继承自该类的任何非抽象类中都必须重写该方法。 如果派生类自身是抽象的,则它继承抽象成员而不实现它们。 抽象成员和虚成员是多态性的基础,多态性是面向对象的编程的第二个主要特性。 有关更多信息,请参见 多态性。
抽象基类
如果希望禁止通过 new关键字直接进行实例化,可以将类声明为abstract
如果这样做,则仅当从该类派生新类时才能使用该类。 抽象类可以包含一个或多个自身声明为抽象的方法签名。
这些签名指定参数和返回值,但没有实现(方法体)。 抽象类不必包含抽象成员;但是,如果某个类确实包含抽象成员,则该类自身必须声明为抽象类。
自身不是抽象类的派生类必须为抽象基类中的任何抽象方法提供实现。 有关更多信息,请参见 抽象类、密封类及类成员。
接口
“接口”是一种引用类型,有点像仅包含抽象成员的抽象基类。 类在从接口实现时必须为该接口的所有成员提供实现。 类虽然只能从一个直接基类派生,但可以实现多个接口。
接口用于为不一定具有“是”关系的类定义特定功能。 例如,System.IEquatable<T> 接口可由任何类或构造实现,这些类或构造必须启用代码来确定该类型的两个对象是否等效(但是该类型定义等效性)。 IEquatable<T> 不表示基类和派生类之间存在的同一种“是”关系(例如
派生类对基类成员的访问
派生类可以访问基类的公共成员、受保护成员、内部成员和受保护内部成员。
即使派生类继承基类的私有成员,仍不能访问这些成员。 但是,所有这些私有成员在派生类中仍然存在,且执行与基类自身中相同的工作。
例如,假定一个受保护基类方法访问私有字段。 要使继承的基类方法正常工作,派生类中必须有该字段。
禁止进一步派生
类可以将自身或其成员声明为 sealed,从而禁止其他类从该类自身或其任何成员继承。 有关更多信息,请参见 抽象类、密封类及类成员。
派生类隐藏基类成员
派生类可以通过以相同的名称和签名声明基类成员来隐藏这些成员。 可以使用 new 修饰符显式指示成员不作为基类成员的重写。 不是必须要使用 new,但如果不使用 new,将生成编译器警告。 有关更多信息,请参见使用 Override 和 New 关键字进行版本控制和 了解何时使用 Override 和 New 关键字。
备注:转自https://msdn.microsoft.com/zh-cn/library/ms173149.aspx
其成员被继承的类称为“基类”,继承这些成员的类称为“派生类”。 派生类只能有一个直接基类。 但是,继承是可传递的。 如果 ClassB
派生出 ClassC,ClassA 派生出 ClassB,则 ClassC 会继承 ClassB 和 ClassA 中声明的成员。
结构不支持继承,但可以实现接口。 有关更多信息,请参见 接口。
从概念上来说,派生类是基类的专用化。 例如,如果您有一个基类
Animal,则可以有一个名为
Mammal的派生类和一个名为
Reptile的派生类。
Mammal是一个
Animal,
Reptile也是一个
Animal,但每个派生类均表示基类的不同专用化。
定义一个类从其他类派生时,派生类隐式获得基类的除构造函数和析构函数以外的所有成员。 因此,派生类可以重用基类中的代码而无需重新实现这些代码。 可以在派生类中添加更多成员。 派生类以这种方式扩展基类的功能。
下图演示一个
WorkItem类,该类表示某业务流程中的一个工作项。 和所有的类一样,该类派生自 System.Object 并继承其所有方法。
WorkItem添加了自己的五个成员。 其中包括一个构造函数,因为构造函数不能继承。 类
ChangeRequest继承自
WorkItem并表示特定种类的工作项。
ChangeRequest在它从
WorkItem和 Object 继承的成员中另外添加了两个成员。 它必须添加其自己的构造函数,还添加
originalItemID。 利用属性
originalItemID,可将
ChangeRequest实例与更改请求将应用到的原始
WorkItem相关联。
下面的示例演示如何以 C# 表示上图所示的类关系。 该示例还演示
WorkItem如何重写虚方法 Object.ToString,以及
ChangeRequest类如何继承该方法的
WorkItem实现。
// WorkItem implicitly inherits from the Object class. public class WorkItem { // Static field currentID stores the job ID of the last WorkItem that // has been created. private static int currentID; //Properties. protected int ID { get; set; } protected string Title { get; set; } protected string Description { get; set; } protected TimeSpan jobLength { get; set; } // Default constructor. If a derived class does not invoke a base- // class constructor explicitly, the default constructor is called // implicitly. public WorkItem() { ID = 0; Title = "Default title"; Description = "Default description."; jobLength = new TimeSpan(); } // Instance constructor that has three parameters. public WorkItem(string title, string desc, TimeSpan joblen) { this.ID = GetNextID(); this.Title = title; this.Description = desc; this.jobLength = joblen; } // Static constructor to initialize the static member, currentID. This // constructor is called one time, automatically, before any instance // of WorkItem or ChangeRequest is created, or currentID is referenced. static WorkItem() { currentID = 0; } protected int GetNextID() { // currentID is a static field. It is incremented each time a new // instance of WorkItem is created. return ++currentID; } // Method Update enables you to update the title and job length of an // existing WorkItem object. public void Update(string title, TimeSpan joblen) { this.Title = title; this.jobLength = joblen; } // Virtual method override of the ToString method that is inherited // from System.Object. public override string ToString() { return String.Format("{0} - {1}", this.ID, this.Title); } } // ChangeRequest derives from WorkItem and adds a property (originalItemID) // and two constructors. public class ChangeRequest : WorkItem { protected int originalItemID { get; set; } // Constructors. Because neither constructor calls a base-class // constructor explicitly, the default constructor in the base class // is called implicitly. The base class must contain a default // constructor. // Default constructor for the derived class. public ChangeRequest() { } // Instance constructor that has four parameters. public ChangeRequest(string title, string desc, TimeSpan jobLen, int originalID) { // The following properties and the GetNexID method are inherited // from WorkItem. this.ID = GetNextID(); this.Title = title; this.Description = desc; this.jobLength = jobLen; // Property originalItemId is a member of ChangeRequest, but not // of WorkItem. this.originalItemID = originalID; } } class Program { static void Main() { // Create an instance of WorkItem by using the constructor in the // base class that takes three arguments. WorkItem item = new WorkItem("Fix Bugs", "Fix all bugs in my code branch", new TimeSpan(3, 4, 0, 0)); // Create an instance of ChangeRequest by using the constructor in // the derived class that takes four arguments. ChangeRequest change = new ChangeRequest("Change Base Class Design", "Add members to the class", new TimeSpan(4, 0, 0), 1); // Use the ToString method defined in WorkItem. Console.WriteLine(item.ToString()); // Use the inherited Update method to change the title of the // ChangeRequest object. change.Update("Change the Design of the Base Class", new TimeSpan(4, 0, 0)); // 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 the Design of the Base Class */抽象方法和虚方法
当基类将方法声明为 virtual 时,派生类可以用自己的实现重写该方法。 如果基类将成员声明为 abstract,则在直接继承自该类的任何非抽象类中都必须重写该方法。 如果派生类自身是抽象的,则它继承抽象成员而不实现它们。 抽象成员和虚成员是多态性的基础,多态性是面向对象的编程的第二个主要特性。 有关更多信息,请参见 多态性。
抽象基类
如果希望禁止通过 new关键字直接进行实例化,可以将类声明为abstract
如果这样做,则仅当从该类派生新类时才能使用该类。 抽象类可以包含一个或多个自身声明为抽象的方法签名。
这些签名指定参数和返回值,但没有实现(方法体)。 抽象类不必包含抽象成员;但是,如果某个类确实包含抽象成员,则该类自身必须声明为抽象类。
自身不是抽象类的派生类必须为抽象基类中的任何抽象方法提供实现。 有关更多信息,请参见 抽象类、密封类及类成员。
接口
“接口”是一种引用类型,有点像仅包含抽象成员的抽象基类。 类在从接口实现时必须为该接口的所有成员提供实现。 类虽然只能从一个直接基类派生,但可以实现多个接口。
接口用于为不一定具有“是”关系的类定义特定功能。 例如,System.IEquatable<T> 接口可由任何类或构造实现,这些类或构造必须启用代码来确定该类型的两个对象是否等效(但是该类型定义等效性)。 IEquatable<T> 不表示基类和派生类之间存在的同一种“是”关系(例如
Mammal是
Animal)。 有关更多信息,请参见 接口。
派生类对基类成员的访问
派生类可以访问基类的公共成员、受保护成员、内部成员和受保护内部成员。
即使派生类继承基类的私有成员,仍不能访问这些成员。 但是,所有这些私有成员在派生类中仍然存在,且执行与基类自身中相同的工作。
例如,假定一个受保护基类方法访问私有字段。 要使继承的基类方法正常工作,派生类中必须有该字段。
禁止进一步派生
类可以将自身或其成员声明为 sealed,从而禁止其他类从该类自身或其任何成员继承。 有关更多信息,请参见 抽象类、密封类及类成员。
派生类隐藏基类成员
派生类可以通过以相同的名称和签名声明基类成员来隐藏这些成员。 可以使用 new 修饰符显式指示成员不作为基类成员的重写。 不是必须要使用 new,但如果不使用 new,将生成编译器警告。 有关更多信息,请参见使用 Override 和 New 关键字进行版本控制和 了解何时使用 Override 和 New 关键字。
备注:转自https://msdn.microsoft.com/zh-cn/library/ms173149.aspx
相关文章推荐
- c#学习笔记五 面向对象编程的基本概念 接口 继承和多态
- 浅谈学习C++时用到的【封装继承多态】三个概念
- iOS概念入门学习-OC-类的继承和派生
- 浅谈学习C++时用到的【封装继承多态】三个概念
- 封装、继承、多态是面向对象编程的三个本质特征。
- C#学习入门概念之三(面向对象三大特性之多态性)
- 关于C#面向对象三个特征:继承,封装,多态的说明
- 关于C#面向对象三个特征:继承,封装,多态的说明
- C++入门学习:多继承的概念及其二义性、虚继承的概念
- (原创)c#学习笔记08--面向对象编程简介02--OOP技术02--继承
- java学习之路 之 高级类特性1-面向对象特征之二:继承及方法重写(override)
- C#中面向对象编程机制之继承学习笔记
- C#学习入门概念之三(面向对象三大特性之多态性)
- 关于C#面向对象三个特征:继承,封装,多态的说明
- C#学习笔记--类的重要特性:继承(转载)
- Java学习笔记1------面向对象的三个基本特征
- C#2.0泛型学习--入门篇
- SAP ABAP/4学习--学习使用OO在ABAP中.简单入门概念.用个例子来说明
- C#学习笔记(二十):Windows应用程序安装部署概念
- C#学习基础概念二十五问第1/4页