欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解C#面相对象编程中的继承特性

程序员文章站 2022-04-29 10:46:49
继承(加上封装和多态性)是面向对象的编程的三个主要特性(也称为“支柱”)之一。 继承用于创建可重用、扩展和修改在其他类中定义的行为的新类。其成员被继承的类称为“基类”,继承...

继承(加上封装和多态性)是面向对象的编程的三个主要特性(也称为“支柱”)之一。 继承用于创建可重用、扩展和修改在其他类中定义的行为的新类。其成员被继承的类称为“基类”,继承这些成员的类称为“派生类”。派生类只能有一个直接基类。但是,继承是可传递的。如果 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#面相对象编程中的继承特性

类继承
下面的示例演示如何以 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