zoukankan      html  css  js  c++  java
  • 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 ;原因不在赘述.
        
       
  • 相关阅读:
    数组的复制
    ==与equals()区别
    构造器与方法
    数据类型及类型转换
    java标识符与命名规则
    多线程 总结
    局部变量与成员变量
    Java反射机制
    java的动态代理机制详解
    USB设备描述符
  • 原文地址:https://www.cnblogs.com/kingcat/p/1229421.html
Copyright © 2011-2022 走看看