• C# new和override


    c#学习中关于new和override的一点小结(转载)

    最近一周在看C#编程语言,由于以前主要用C语言,在看到new和override两种方法对基类方法不同影响时有点迷糊。花了点时间查了下资料又自己实验了一下,在此小结一下,也算是便于自己记忆吧。

    首先,继承不是子类附着到基类上,而是子类先复制基类的成员,再添加上自己的东西形成一个新的整体。

    比如按如下定义的两个类:

    他们之间的继承关系可以用下图来表示:

    class son首先复制parent的两个成员:变量i和方法test(),然后再附加上自己的成员。这时候注意:new关键字定义的test()方法并没有覆盖掉从parent继承过来的方法,而是自己在旁边又新开了一个方法。那么new是怎么来隐藏继承得到的test()方法的呢?

    当我们实例化一个对象,son aOfSon = new son();  这时候aOfSon的类型是son类型,那么son类型的成员列表中有{ j , i , test(), test2()} , 成员指向的对象如图所示:

    当调用aOfSon.test()的时候指向的是新建立的new test(),从而隐藏了从基类继承而来的test()。

    现在我们转换aOfSon的类型,将其隐式地转换为parent类型 parent aOfPar = aOfSon;

    这时候aOfPar是parent类型,parent中只有两个成员变量{ i ,  test()} ,其指向如下图所示

    尽管此时aOfPar在堆中分配的内存中可能还是存在j,new test()和test2(),(此处为猜想,未验证)

    但是此时它的类型为parent,不包含对这三个成员的引用,因此无法访问这三个成员。且parent型中的test()成员指向的是老位置上存在的那个旧的test()方法。

    上诉的验证代码如下:

    //实例化对象

                son aOfSon = new son();
                parent aOfPar = aOfSon;

    //调用函数

                Console.WriteLine("Run aOfSon.test()");
                aOfSon.test();
                Console.WriteLine();

                Console.WriteLine("Run aOfPar.test()");
                aOfPar.test();
                Console.WriteLine();

    得到的结果如下:

    override与new不同的在于它不是在继承而来的test()旁边新建了一个new test(),而是直接覆盖了继承而来的test()

    现将两个类定义如下

    它们之间的继承关系如下图所示:

    class son首先复制parent的两个成员:变量i和方法test(),然后再附加上自己的成员。这时候注意,class son中的test()方法覆盖了继承而来的test()方法,占领了原先旧方法的位置。

    这时候son类型对象的成员指向情况如下图所示:

    parent类型对象的成员指向如下图所示

    关键在于子类重写的test()方法占据了原本继承而来的test()方法的位置,所以当用parent型对象调用test()方法时,它指向的是新建立的test()方法(实际上它的指向位置没有变)。

    那么既然我们已经重写了基类的test()方法,那么为什么在test2()中还能通过base来访问原本的test()方法呢?

    这就是因为继承并不是直接在基类上做更改,而是先创建一个基类的副本,然后再此基础上做修改。在test2()中我们又从基类复制了它的test()方法并封装在test2()方法中。

    如下图所示

    测试代码如下:

    //实例化对象

                son aOfSon = new son();
                parent aOfPar = aOfSon;

    //调用函数

                Console.WriteLine("Run aOfSon.test()");
                aOfSon.test();
                Console.WriteLine();

                Console.WriteLine("Run aOfPar.test()");
                aOfPar.test();
                Console.WriteLine();

                Console.WriteLine("Run aOfSon.test2()");
                aOfSon.test2();
                Console.WriteLine();

    得到结果如下图:

    最后关于virtual和abstract的区别,virtual定义的方法中可以有方法体,且可以被对象直接调用

    如上面定义的类,实例化一个基类的对象            parent bOfPar = new parent();

    调用它的test()方法

                Console.WriteLine("Run bOfPar.test()");
                bOfPar.test();
                Console.WriteLine();

    得到结果如下图

    virual定义表示这个方法可以被重写,但不是必须的

    abstract只能在抽象类中定义抽象方法,它是空的(没有方法体),在继承它的子类中必须重写该方法

  • 相关阅读:
    华为数据之道03
    机器学习10讲 第二讲
    机器学习10讲 第一讲
    07.TensorFlow双向循环神经网络
    06.TensorFlow循环神经网络
    华为数据之道:华为数据治理2
    线性回归
    MySQL配置文件my.cnf的理解
    Linux怎么查看软件安装路径 查看mysql安装在哪
    hadoop-2.7.4-nodemanager无法启动问题解决方案
  • 原文地址:https://www.cnblogs.com/yaphetsfang/p/9327279.html
Copyright © 2020-2023  润新知