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

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

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

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

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

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

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

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

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

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

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

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

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

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

尽管此时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();

得到的结果如下:

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

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

现将两个类定义如下

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

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

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

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

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

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

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

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

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

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

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

如下图所示

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

测试代码如下:

//实例化对象

            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();

得到结果如下图:

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

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

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

调用它的test()方法

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

得到结果如下图

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

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

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

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