继承(上)

      继承是面向对象编程中一个非常重要的特性,它也是另一个重要特性——多态的基础。

4.1继承概念的引入

      现实生活中的事物都归属于一定的类别。比如,狮子是一种( IS_A)动物。为了在计

算机中摸拟这种关系,面向对象的语言引入了继承(inherit的特性。

      如图 所示,用类  Animal代表动物,用类  Lion代表狮子,用一个空心的三角箭头表

示继承关系。

      构成继承关系的两个类中,Animal称为父类(parent  class)或基类(base  class),Lion

称为子类(child class)。

提示:

      在一些书中,将父类称为超类(super class)。

      “继承关系有时又称为派生关系,“B 继承自  A”,可以说为“B 派生自  A”,或

反过来说,“A 派生出 B”

父类与子类之间拥有以下两个基本特性:

  • 是一种(IS-A)关系:子类是父类的一种特例。
  • 扩充(Extends)关系:子类拥有父类所没有的功能。

以下 C#代码实现了狮子类与动物类之间的继承关系:

      可以看到,C#中用一个冒号间隔开父类和子类。

4.2类成员的访问权限

      面向对象编程的一大特点就是可以控制类成员的可访问性。当前主流的面向对象语言都

拥有以下三种基本的可访问性(表  2):

                            表  2类成员的访问权限

(1)public和   private

public和  private主要用于定义单个类的成员存取权限。

请看以下示例代码:

   public class  A

{

    public int publicI;

    private int privateI;

    protected int protectedI;

  }

当外界创建一个 A的对象后,只能访问  A的公有实例字段  publicI:

A a = new A();

a.publicI = 100; //OK!

类 A的私有实例字段  privateI只能被自身的实例方法所使用:

   public class  A

{

    public int publicI;

    private int privateI;

    protected int protectedI;

    private void f()

 {

        privateI = 100;  //OK!

    }

    }

      上述代码中,类 A的私有方法  f()访问了私有字段 privateI。注意,只要是类 A直接定义

的实例方法,不管它是公有还是私有的,都可以访问类自身的私有实例字段。

(2)protected

      在形成继承关系的两个类之间,可以定义一种扩充权限——protected。

      当一个类成员被定义为  protected之后,所有外界类都不可以访问它,但其子类可以访

问。

      以下代码详细说明了子类可以访问父类的哪些部分(示例项目 Inherits):

      class  Parent

{

       public int publicField=0;

       private int privateFiled=0;

       protected int protectedField=0;

       protected void protectedFunc()

      { }

}

class  Son:Parent

{

      public void ChildFunc()

   {

        publicField = 100;//正确!子类能访问父类的公有字段

        privateFiled = 200;//错误!子类不能访问父类的私有字段

        protectedField = 300; //正确!子类能访问父类的保护字段  

        protectedFunc(); //正确!子类能访问父类的保护方法

      }

}

      当创建子类对象后,外界可以访问子类的公有成员和父类公有成员,如下所示:

      由此可见,可以通过子类对象访问其父类的所有公有成员,事实上,外界根本分不清

楚对象的哪些公有成员来自父类,哪些公有成员来自子类自身。

      小结一下继承条件下的类成员访问权限:

  •   所有不必让外人知道的东西都是私有的。
  •   所有需要向外提供的服务都是公有的。
  •   所有的祖传绝招秘不外传的都是保护的。

(3)internal

      C#中还有一种可访问性,就是由关键字 internal所确定的内部访问性。

      internal有点像  public,外界类也可以直接访问声明为 internal的类或类的成员,但这只

局限于同一个程序集内部。

      读者可以简单地将程序集理解为一个独立的 DLL或  EXE文件。一个  DLL或  EXE文件

中可以有多个类,如果某个类可被同一程序集中的类访问,但其他程序集中的类不能访问它,

则称此类具有 internal访问性。

      例如类库项目    ClassLibrary1可以生成一个独立的程序集(假定项目编译后生成

ClassLibrary1.DLL),其中定义了两个类 A和  B:

namespace  ClassLibrary1

{

        internal  class  A

     {

             internal int  InternalI=0;

      }

public class  B

{

     public void  f()

   {

       A a = new  A(); //OK!

        a. InternalI= 100;   //OK!

    }

 }

}

      由于类 B与类  A属于同一个程序集,所以,B中的代码可以创建   A的对象,并访问   A

的声明为 internal的成员  InternalI。

      在程序集 ClassLibrary1.DLL之外,外界只能创建声明为  public的类  B的对象,不能创

建声明为 internal的类  A的对象。

      internal是  C#的默认可访问性,这就是说,如果某个类没有任何可访问性关键字在它前

面,则它就是internal

      比如上面的类 A也可以写成:

      它完全等同于

      但要注意,在类中,如果省略成员的可访问性关键字,则默认为 private的。

      例如:

      相当于

      为便于读者查阅,将 C# 2.0和  Visual Basic 2005的存取权限总结如表   3所示。

表  3类型存取权限一览表

 

4.3子类父类变量的相互赋值

      构成继承关系的父类和子类对象之间有一个重要的特性:

            子类对象可以被当成基类对象使用。

      这是因为子类对象本就是一种(IS_A)父类对象,因此,以下代码是合法的:

Parent p;

Son c = new Son  ();

p = c;  //正确,子类对象可以传给父类变量

      上述代码中 Parent是  Son类的父类。

      然而,反过来就不可以,以下代码是错误的:

c = p;  //错误,父类对象变量不可以直接赋值给子类变量

      如果确信父类变量中所引用的对象的确是子类类型,则可以通过类型强制转换进行赋

值,其语法格式为:

子类对象变量=(子类名称)基类对象变量;

      或使用 as运算符

子类对象变量=基类对象变量 as 子类名称;

      示例代码如下:

c = (Child)p; //正确,父类对象变量引用的就是子类对象

      或

c = p as Child  ;

posted on 2015-02-26 10:26  星空丶那一抹流光  阅读(169)  评论(0编辑  收藏  举报

导航