ClassBase A = New ClassSon() 全面分析

      先看如下的代码:
 1
 2public class BaseClass
 3{
 4    public string str = "基类的字段";
 5
 6    public virtual string A()
 7    {
 8        return "基类的方法A";
 9    }

10
11    public string B()
12    {
13        return "基类的方法B";
14    }

15}

16
17
18public class SonClass : BaseClass
19{
20    public string str = "子类的字段";
21
22    public override string A()
23    {
24        return "子类的方法A";
25    }

26
27    new public string B()
28    {
29        return "子类的方法B";
30    }

31}

这段代码很简单,定义了一个基类和一个继承它的子类.
   
    在面向对象的的概念中,最基础的应该就是继承了.继承概念很简单:基础类的公有元素(字段,属性,方法)可以被继承它的子类使用,就如同子类自己定义的一样,如果觉得基类定义的方法不太爽,还可以自己写一个同名的方法覆盖它,这就是所谓的重写(override),比如代码红的方法A(), 但是实现方法的重写是有条件的,基类的方法是公有,切是虚方法.那假如基类的某方法是公有但不是虚方法,而在子类中我也想重新定义呢,比如说方法B(),这时候C#就有了应藏方法的概念.即:在子类中对基类中非虚方法的另一种重写,子类在隐藏基类的方法时,可在方法前面增加一关键字 NEW(也可以不加),如子类中的方法B().
    说完了重写和覆盖,看如下代码:
SonClass Me = new SonClass();
Me.str; Me.A(); Me.B();
或者:
BaseClass Base = new BaseClass ();
Base .str; Base .A(); Base .B();
输出结果一目了然,不必多费口舌.

    再看如下代码:
BaseClass Me = new SonClass();
Me.str; Me.A(); Me.B();
大家就可能有点迷糊了,即使知道输出结果,但为什么是这样的输出,可能还是糊涂.我看过好几本还算不错的书,包括博客园出的一本<你必须知道的.NET>,说实话,在对这个知识点的描述上实在不敢恭维. 后来查资料有这么一段描述:如果是重写,则,如果声明的基类对象,指向的是派生类,那么这时调用的是派生类中对基类方法重写的方法,也就是说Me.A(); 执行的是SonClass类中对BaseClass.A()重写的方法,即SonClass.A(). 如果是隐藏,则,如果声明的基类对象,指向的是派生类,那么这时调用的是基类中的方法,也就是说Me.B(); 执行的是BaseClass.B(). 再看看Me.str,它调用的是类中的字段,它其实是和方法B()情况是一样的,只是没有在子类中增加关键字NEW而已.所以,Me.str调用的也是BaseClass.str.

    再说一下BaseClass Me = new SonClass(); 这种基类/子类相互之间的定义引用,先让我们看看该代码表示的意思:
    BaseClass Me = new SonClass(); 表示,要在堆栈中定义一个类型为BaseClass的指针变量Me,指向的是堆中具体定义的类SonClass的实例, 和该代码对应的:SonClass Me = new SonClass(); 表示要在堆栈中定义一个类型为SonClass的指针变量Me,指向的是堆中具体定义的类SonClass的实例,由此可以知道,在这两句代码执行完毕后,实例化的类都是SonClass,但代表它们的对象指针类型是不一样的,一个是BaseClass 一个是 SonClass . 就以上申明来说,申明了一个基类的变量,实际指想的是子类的一个实例.这是允许的,那反过来呢:SonClass Me = new BaseClass(); 是不允许的,打个比喻,父亲会修自行车,也会修鞋,他把这些技能传给了儿子(继承),而儿子不但掌握了父亲的这两样技能,还自学了修汽车的技能. 经过SonClass Me = new SonClass(); 之后,ME的身份就成了父亲,他对外只接受修自行车和修鞋的工作,但是实际上这些工作是由他的儿子new SonClass()来完成的,因为他只是个代表.真正工作的是儿子.他接受的工作他儿子都能完成,因为他把这些工作的技能继承给了他儿子. 那反过来呢SonClass Me = new BaseClass(); ME的身份就成了儿子,实际完成工作的是父亲,如果儿子接受了修自行车,修鞋的工作父亲还可以应付,但如果儿子接受了修汽车的工作呢?

    最后再补充一下这种情况说明BaseClass Me = new SonClass();  SonClass Me1 = (SonClass )Me 是合法的,因为在这里Me 虽然是基类类型,但它实际指向的是子类BaseClass Me = new SonClass(); ,而在类型转换时SonClass Me1 = (SonClass )Me ,通过Me编译器会找到它所代表的真正实例是SonClass,而SonClass Me1 = (SonClass )Me(实际是SonClass的实例 )是合法的. 但是如果是这种情况,执行会失败:BaseClass Me = new BaseClass ();  SonClass Me1 = (SonClass )Me ;原因不在赘述.
    
   
posted on 2008-06-25 10:38  老金  阅读(666)  评论(0编辑  收藏  举报