详解C#面相对象编程中的继承特性
作者:goldensun 发布时间:2022-06-09 09:15:24
继承(加上封装和多态性)是面向对象的编程的三个主要特性(也称为“支柱”)之一。 继承用于创建可重用、扩展和修改在其他类中定义的行为的新类。其成员被继承的类称为“基类”,继承这些成员的类称为“派生类”。派生类只能有一个直接基类。但是,继承是可传递的。如果 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();
}
}
输出:
1 - Fix Bugs
2 - Change the Design of the Base Class


猜你喜欢
- 为大家分享的解决MyEclipse中的Building workspace问题的方法如下方法一:点击“Project”,取消勾选“Build
- 1.Semaphore的概述public class Semaphore extends Object implements Seriali
- 本文实例讲述了Winform启动另一个项目传值的方法。分享给大家供大家参考。具体如下:背景:从A项目中登陆后,跳转到B项目的某个页面(B不再
- 前言在上一篇 Spring boot + LayIM + t-io 文件上传、 监听用户状态的实现 中,已经介绍了两个小细节:用户的在离线状
- 我的环境* JDK 1.8 * maven 3.6.0 * node环境1.为什么需要前后端项目开发时分离,部署时合并?
- 牛逼!IDEA不愧为神器,结合Groovy脚本,简直天下无敌,如今, 有许许多多的插件或者编辑器都支持根据数据表自动生成数据实体类了, 比如
- 下面是我自己收集整理的2017年Java岗位的面试题,可以用它来好好准备面试。一、Java基础1. String类为什么是final的。2.
- 本文实例为大家分享了Unity Shader实现动态过场切换图片的具体代码,供大家参考,具体内容如下一、简单介绍Shader Languag
- 本文实例为大家分享了Android自定义轮播图的具体代码,供大家参考,具体内容如下定义Banner主要使用ViewPager实现滑动publ
- 最终版iTextSharp 5.5: https://github.com/itext/itextsharp ,已经被 iText 7代替。
- 前言Java中的原生反射库虽然方法不多,但写起来却非常繁琐, 比如:public static <T> T create(Htt
- 场景:使用Fragment实现切页。类结构:一:ActivityActivity中使用getSupportFragmentManager()
- ApplicationContext简述ApplicationContext代表IOC容器,在SpringIOC容器中读取Bean配置创建B
- 在使用SuperSocket来写服务器的过程中,这是一个非常快速的开发方式,也非常好用。不过学习的曲线有点高,在使用的过程中经常会遇到各种各
- 最近在刷力扣上的题目,刷到了65不同路径,当初上大学的时候,曾在hihocoder上刷到过这道题目,但是现在已经几乎全忘光了,大概的知识点是
- 在练习Java的Scanner时,EditPlus如何读取从键盘输入的数呢?例如如下程序,编译通过,运行时却输入不了数据:package m
- 1、很多资料说,添加以下代码,可以隐藏地址栏,但我试了很多次,貌似不成功啊。<meta name="apple-mobile
- 本文实例讲述了C#调用存储过程的方法。分享给大家供大家参考,具体如下:CREATE PROCEDURE [dbo].[GetNameById
- 本文实例实现一个如下图所示的Android自定义控件,可以直观地展示某个球队在某个赛季的积分数和胜场、负场、平局数首先对画布进行区域划分,整
- Java把内存分成两种,一种叫做栈内存,一种叫做堆内存在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。