代码改变世界

C#学习笔记(六):类成员的其他议题

2006-01-12 10:56  努力学习的小熊  阅读(1047)  评论(0编辑  收藏  举报

一、隐藏基类的方法

当从基类继承一个(非抽象的)成员时,也就继承了其执行代码。如果继承的成员是虚拟的virtual,就可以用override关键字重写(重载)这段代码。无论继承的成员是否是虚拟的,我们都可以隐藏这些执行代码。例如:

    public class MyBaseClass

    {

        public void DoSomething()

        {

            //Base implementation

        }

    }

 

    public class MyDerivedClass : MyBaseClass

    {

        new public void DoSomething()

        {

            //Derived class implementation,hides base implementation

        }

}

在这里我们应该注意隐藏基类成员和重载它们的区别。

    public class MyBaseClass

    {

        public virtual void DoSomething()

        {

            Console.WriteLine("Base imp");

        }

    }

 

    public class MyDerivedClass : MyBaseClass

    {

        public override void DoSomething()

        {

            Console.WriteLine("Derived imp");

        }

}

其中重载的方法将替换积累中的执行代码,这样下面的代码将使用新的版本,即使这是通过基类执行的,情况也是这样(多态性)

            MyDerivedClass myObj = new MyDerivedClass();

            MyBaseClass myBaseObj;

            myBaseObj = myObj;

            myBaseObj.DoSomething();

执行结果为:

Derived imp

 

大家可以看到,这样设计类有一个好处,在初版中很可能功能不会完善,有些方法不对用户开放,当版本升级后便可以通过这种代码升级很容易的实现而不用去修改很多其他地方的代码。或者在不断修改完善方法的功能时也可以很方便的实现一处修改即可实现多处的维护。而且一旦做了myBaseObj = myObj后,可以使用户无法访问到基类的代码块

 

我们将代码作如下修改,使用new关键字我们实现了即使有myBaseObj = myObj的类“升级”,但是我们还是能访问到这个对象的基类的方法。它们互不影响。

    public class MyBaseClass

    {

        public virtual void DoSomething()

        {

            Console.WriteLine("Base imp");

        }

    }

 

    public class MyDerivedClass : MyBaseClass

    {

        new public void DoSomething()

        {

            Console.WriteLine("Derived imp");

        }

    }

我们将调用代码修改为如下即可看到结果:

            MyDerivedClass myObj = new MyDerivedClass();

            MyBaseClass myBaseObj;

            myBaseObj = myObj;

            myBaseObj.DoSomething();

            myObj.DoSomething();

执行结果为:

Base imp

Derived imp

 

二、调用重写或隐藏的积累代码

无论是重写成员还是应藏成员,都可以在类的内部访问基类成员。

1.要对派生类的用户隐藏继承的公共成员,但仍能在类中访问其功能。

2.要给继承的虚拟成员添加执行代码,而不是简单的用新的重写的执行代码替换它。

这里简单的研究了一下继承和派生的区别:

例如:基类A

      B直接继承于A

      C直接继承于B

 

    那么依据上面的说法则有:

 

      A派生类B,类A被类B继承;类B派生类C, 类B被类C继承。

      B是类A的子类,类C是类B的子类;

      B和类C都是类A的派生类。

继承和派生从两个不同的角度来说明的,举例如下:

AB的子类,则我们可以说B继承A,是A的派生类

但如果有CB的子类,就不能说C继承A,而只能说CA的派生类。其实就是隔代的问题。

 

我们使用base关键字,它表示包含在派生类中的基类的执行代码。例如:


    我们在其继承类MyDerivedClass中利用base关键字可以访问到其方法。这里我们再定义一个继承于MyDerivedClass的类tempclass类,这时我们再使用base关键字会发现DoSomething这个方法有两种方法:

一个是MyDerivedClass.DoSomething()


    一个是MyBaseClass.DoSomething()


    除了使用base关键字外我们还可以使用this关键字。与base关键字一样,this也可以用在类成员的内部,且该关键字也引用对象实例。由this关键字引用的对象实例是当前的对象实例(即不能在静态成员中使用this关键字,因为静态成员不是对象实例的一部分)。

我们还是定义了如下的两个类:

    public class MyBaseClass

    {

        public virtual void DoSomething()

        {

            //Base implementation

            Console.WriteLine("Base Method");

        }

    }

 

    public class MyDerivedClass : MyBaseClass

    {

        public override void DoSomething()

        {

            //Derived class implementation,hides base implementation

            base.DoSomething();

            //More derived class implementation

        }

 

        public void DoAnothorthing()

        {

            Console.WriteLine("Anothor Method");

        }

 

        public string aa;

    }

然后我们定义第三个类去做这个实验:

这里我们发现无论是this关键字还是base关键字都可以访问到其基类的成员,但是如果将其基类成员作如下修改的话,将DoAnothorthing()方法和字符串变量aa均定义为静态成员:

    public class MyBaseClass

    {

        public virtual void DoSomething()

        {

            //Base implementation

            Console.WriteLine("Base Method");

        }

    }

 

    public class MyDerivedClass : MyBaseClass

    {

        public override void DoSomething()

        {

            //Derived class implementation,hides base implementation

            base.DoSomething();

            //More derived class implementation

        }

 

        public static void DoAnothorthing()

        {

            Console.WriteLine("Anothor Method");

        }

 

        public static string aa;

    }

如下图,我们会发现无论是this关键字还是base关键字都访问不到这两个静态成员了。

this关键字最常用的功能就是将一个当前对象实例的引用传递给一个方法,例如:

        public void doSomething()

        {

            MyTargetClass myObj = new MyTargetClass();

            myObj.DoSomethingWith(this);

        }