且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

(教学思路 C#之类八)多态性:base、new、override、virtual

更新时间:2022-09-17 20:22:22

  本篇博客我们来学习面向对象的多态性,多态性主要的表现形式就是在继承中当派生类从基类继承时,它会获得基类的所有方法、字段、属性和事件。当父类和子类的成员签名相同的时候,我们可以定义让子类的这个同名成员以何种形式显示出来,父类的这个的成员在子类中又用何种方式存在,这种多面的表现方法我们称为多态。如果我们要更改基类的数据和功能时,也就是说子类中可以以自己的方式去实现父类的功能,有两种方式:1.我们还在子类中可以使用override关键字重写基类中用virtual关键字修饰的虚拟的基成员;2.可以在子类中使用new关键字让派生成员替换基成员,此时基类成员只是被有意的隐藏掉了。
    举一个现实生活的例子,我们来理解一下多态,爸爸如果有一套房子留给了儿子,并对儿子说:这个房子我装修了一下,如果你不喜欢这个风格,可以自己再重新翻新一下,但是我就有一个要求,就是这个房子唯一不变就是我喜欢的挂在走廊墙上的一张油画,你不许拆掉它。儿子欣然同意,拿到钥匙去看了看房子,儿子有点对爸爸的审美产生了质疑,装修的风格也太古朴了,于是儿子决定把客厅和卧室全部装修了,改成了后现代主义的风格,这时发生了我们所说的多态的第一种方式,被称为重写或覆写,爸爸给房子时,把允许重新装修的地方用virtual关键字修饰,儿子就可以用override关键字修饰那些允许重新装修的房间,这时父亲来到这个房子时会发现房子的客厅和卧室全部改变了。装修完客厅和卧室后,儿子怎么看都觉得走廊上的油画太格格不入了,因为油画的内容是田园风情,这时儿子想起爸爸不让动这幅画,所以儿子想到了一个方法,就买了一副新的抽象派的油画盖在爸爸的画上面,这样爸爸如果来到家,想看自己的画,也是存在的,这时发生的就是第二种方式,如果爸爸想在儿子的房子里看自己的东西,就使用base关键字,儿子的新油画用new关键字隐藏住爸爸的话。
     通过这个例子我们应该就能理解一点多态的含义了,我们先来学习第一种情况:重写。在使用重写的时候,一定要注意到一点,就是为了让子类可以完全的重写父类中的成员,父类在定义这些成员的时候,一定要使用virtual关键字,让可以重写的方法成为虚方法,让可以重写的属性成为虚属性,子类在重写这个方法或属性的时候,将virtual替换成override关键字,代表已将父类的成员替换为了它自己的成员并实现。我们来看一下具体的语法,为了举例方便,我采用的是方法重写的实例,如:
 class FatherClass
{public virtual  void  Method(){}}
class SonClass:FatherClass
{public override  void  Method(){}}
     大家来看看父类中的方法,按照我们上节课所学的如果父类中的成员不是private修饰时,子类中是都可以访问到一个成员,但是重写是特殊的,根据我举的例子大家回忆一下,这时如果父亲来到儿子的房子,将会只存在被儿子重新装修的客厅和卧室,这两个屋原来的风格都不存在了。也就是说,在子类中,这两个屋子只有一种形态,就是儿子重新装修定义的。虽然其他的屋子父亲也允许儿子装修,使用了virtual关键字修饰了,但是因为儿子没有使用override关键字重新装修,其他几个屋的表现形态还是父亲原先存在的。这就说明了一点,子类要想重写父类的方法,必须是父类定义了virtual,子类使用override。当如果我想在子类的方法中再用父类的那个被覆盖的方法时,只需要使用base关键字就可以代表继承的父类了,base关键字我们在上节课的类七构造方法的继承中也学到过。我们把上面的语法在子类的Method方法中,加base用法,基本语法如下:
public override  void  Method()
{
base.Method();
}
     这样的话,在调用子类的Method方法时,虽然重写了这个方法,但是使用base关键字又再次引用了父类的Method方法。
      当父类定义了virtual,而子类的同名方法没有使用override重写,这样是可以的,这时子类中仍然包括父类的方法,也就是说子类中有两个同名的方法,但是编译器在我们创建子类对象的时候,会显示子类的方法,而不会显示继承自父类那个同名的方法。如果你使用VS编译这样情况时,它会有一个警告:子类的方法将隐藏父类的方法。如果想重写请在子类中加入override关键字,如果想隐藏请使用new关键字。使用override关键字刚才我们已经讲过了,如果用new就代表创建一个新的方法,这个子类中的新方法隐藏父类的方法,这就是我们说的第二种多态的形式隐藏父类的方法。
         隐藏父类方法,父类可以是virtual修饰的虚方法,也可以是普通方法应该在子类中显式的使用new关键字,告知编译器当调用子类的这个方法时,请显示出子类自定义的功能,当然如果要显示父类的方法也同样可以使用base关键字,我们来看下面的语法:
       class FatherClass
{public   void  Method(){}}
    class SonClass:FatherClass
{public new  void  Method()
{
base.Method();
}
}
     我今天所举出的实例比较简单,就是定义了3个类一个包含入口函数的Program类、一个F类,一个S类继承了F类,在F和S中各定义了3个方法,对照结果我们来看一下:
重写和隐藏父类方法实例
(教学思路 C#之类八)多态性:base、new、override、virtual    1 //定义一个F类 
(教学思路 C#之类八)多态性:base、new、override、virtual    2        class F 
(教学思路 C#之类八)多态性:base、new、override、virtual    3        { 
(教学思路 C#之类八)多态性:base、new、override、virtual    4                //定义一个公有Method方法,子类中用new隐藏了本方法 
(教学思路 C#之类八)多态性:base、new、override、virtual    5                public void Method() 
(教学思路 C#之类八)多态性:base、new、override、virtual    6                { 
(教学思路 C#之类八)多态性:base、new、override、virtual    7                        Console.WriteLine("我是父类中的Method方法"); 
(教学思路 C#之类八)多态性:base、new、override、virtual    8                        Console.WriteLine(); 
(教学思路 C#之类八)多态性:base、new、override、virtual    9                } 
(教学思路 C#之类八)多态性:base、new、override、virtual 10                //定义了一个虚方法Method1,子类中重写了Method1. 
(教学思路 C#之类八)多态性:base、new、override、virtual 11                public virtual void Method1() 
(教学思路 C#之类八)多态性:base、new、override、virtual 12                { 
(教学思路 C#之类八)多态性:base、new、override、virtual 13                        Console.WriteLine("我是父类中的Method1方法"); 
(教学思路 C#之类八)多态性:base、new、override、virtual 14                        Console.WriteLine(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 15                } 
(教学思路 C#之类八)多态性:base、new、override、virtual 16                //定义了一个虚方法Method2,子类中重写了Method2.子类中使用了base.method1,再次调用被重写了的Method1 
(教学思路 C#之类八)多态性:base、new、override、virtual 17                public virtual void Method2() 
(教学思路 C#之类八)多态性:base、new、override、virtual 18                { 
(教学思路 C#之类八)多态性:base、new、override、virtual 19                        Console.WriteLine("我是父类中的Method2方法"); 
(教学思路 C#之类八)多态性:base、new、override、virtual 20                        Console.WriteLine(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 21                } 
(教学思路 C#之类八)多态性:base、new、override、virtual 22        } 
(教学思路 C#之类八)多态性:base、new、override、virtual 23        //定义一个继承F类的S类 
(教学思路 C#之类八)多态性:base、new、override、virtual 24        class S : F 
(教学思路 C#之类八)多态性:base、new、override、virtual 25        { 
(教学思路 C#之类八)多态性:base、new、override、virtual 26                //定义一个公有Method方法,隐藏了父类的方法 
(教学思路 C#之类八)多态性:base、new、override、virtual 27                public new void Method() 
(教学思路 C#之类八)多态性:base、new、override、virtual 28                { 
(教学思路 C#之类八)多态性:base、new、override、virtual 29                        Console.WriteLine("我是子类中的Method方法,使用new关键字,显式的隐藏父类中的同名方法"); 
(教学思路 C#之类八)多态性:base、new、override、virtual 30                        Console.WriteLine(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 31                } 
(教学思路 C#之类八)多态性:base、new、override、virtual 32                //定义一个重写父类Method1的方法Method1。 
(教学思路 C#之类八)多态性:base、new、override、virtual 33                public override    void Method1() 
(教学思路 C#之类八)多态性:base、new、override、virtual 34                { 
(教学思路 C#之类八)多态性:base、new、override、virtual 35                        Console.WriteLine("我是子类中的Method1方法,覆盖父类中的同名方法,此时S中没有了父类中Method1方法"); 
(教学思路 C#之类八)多态性:base、new、override、virtual 36                        Console.WriteLine(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 37                } 
(教学思路 C#之类八)多态性:base、new、override、virtual 38                //定义一个重写父类Method1的方法Method1,同时使用base调用父类的Method1。 
(教学思路 C#之类八)多态性:base、new、override、virtual 39                public override    void Method2() 
(教学思路 C#之类八)多态性:base、new、override、virtual 40                { 
(教学思路 C#之类八)多态性:base、new、override、virtual 41                         
(教学思路 C#之类八)多态性:base、new、override、virtual 42                        Console.WriteLine("我是子类中的Method2,覆盖父类中的同名方法,调用base.method1"); 
(教学思路 C#之类八)多态性:base、new、override、virtual 43                        base.Method1(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 44                        Console.WriteLine(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 45                } 
(教学思路 C#之类八)多态性:base、new、override、virtual 46        } 
(教学思路 C#之类八)多态性:base、new、override、virtual 47    
(教学思路 C#之类八)多态性:base、new、override、virtual 48     
(教学思路 C#之类八)多态性:base、new、override、virtual 49        class Program 
(教学思路 C#之类八)多态性:base、new、override、virtual 50        { 
(教学思路 C#之类八)多态性:base、new、override、virtual 51                static void Main(string[] args) 
(教学思路 C#之类八)多态性:base、new、override、virtual 52                { 
(教学思路 C#之类八)多态性:base、new、override、virtual 53                        // 创建一个S类的s对象 
(教学思路 C#之类八)多态性:base、new、override、virtual 54                        S s = new S(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 55                        // 创建一个F类的f对象 
(教学思路 C#之类八)多态性:base、new、override、virtual 56                        F f = new F(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 57 
(教学思路 C#之类八)多态性:base、new、override、virtual 58                        //创建一个F类的fs对象,但是用S类来实现,这种方式是允许的。 
(教学思路 C#之类八)多态性:base、new、override、virtual 59                        //意思就是父亲到了儿子的房子去了,看到的油画应该是父亲的油画,房子还是从父亲那继承下的房子。 
(教学思路 C#之类八)多态性:base、new、override、virtual 60                        //对象fs所引用出的成员,实际是从父类中继承来的成员,不是继承来的成员(如儿子自己买的电器)fs是无权访问的。 
(教学思路 C#之类八)多态性:base、new、override、virtual 61                        //父类需要子类去实现的这种方式会在抽象类和接口中会用到。 
(教学思路 C#之类八)多态性:base、new、override、virtual 62                        F fs = new S(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 63 
(教学思路 C#之类八)多态性:base、new、override、virtual 64                        //先观察一下子类使用new的Method方法中三对象的结果。 
(教学思路 C#之类八)多态性:base、new、override、virtual 65                         //------------------------------------------- 
(教学思路 C#之类八)多态性:base、new、override、virtual 66                        //子类的对象s引用的Method方法打印出的是子类的Method方法 
(教学思路 C#之类八)多态性:base、new、override、virtual 67                        s.Method(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 68                        //子类中的Method方法,因为使用了new,只是覆盖了父类的Method方法, 
(教学思路 C#之类八)多态性:base、new、override、virtual 69                        //所以父类的对象fs引用的Method方法打印出的是还是从父类中继承下来的Method方法 
(教学思路 C#之类八)多态性:base、new、override、virtual 70                        fs.Method(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 71                        //父类中的Method方法不变 
(教学思路 C#之类八)多态性:base、new、override、virtual 72                        f.Method(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 73                        Console.WriteLine("---------"); 
(教学思路 C#之类八)多态性:base、new、override、virtual 74 
(教学思路 C#之类八)多态性:base、new、override、virtual 75 
(教学思路 C#之类八)多态性:base、new、override、virtual 76                        //先观察一下子类使用override的Method1方法中三对象的结果。 
(教学思路 C#之类八)多态性:base、new、override、virtual 77                        //------------------------------------------- 
(教学思路 C#之类八)多态性:base、new、override、virtual 78                        //子类的对象s引用的Method1方法打印出的是子类的Method1方法 
(教学思路 C#之类八)多态性:base、new、override、virtual 79                        s.Method1(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 80                        //子类中的Method1方法,因为使用了override,重写了父类的Method1方法, 
(教学思路 C#之类八)多态性:base、new、override、virtual 81                        //所以父类的对象fs引用的Method1方法打印出的是还是从子类中继承下来的Method1方法 
(教学思路 C#之类八)多态性:base、new、override、virtual 82                        //子类中只存在子类的Method1方法,结果如上. 
(教学思路 C#之类八)多态性:base、new、override、virtual 83                        fs.Method1(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 84                        //父类中的Method方法不变 
(教学思路 C#之类八)多态性:base、new、override、virtual 85                        f.Method1(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 86                        Console.WriteLine("---------"); 
(教学思路 C#之类八)多态性:base、new、override、virtual 87 
(教学思路 C#之类八)多态性:base、new、override、virtual 88 
(教学思路 C#之类八)多态性:base、new、override、virtual 89                        //先观察一下子类使用override和base.method1的Method2方法中三对象的结果。 
(教学思路 C#之类八)多态性:base、new、override、virtual 90                        //------------------------------------------- 
(教学思路 C#之类八)多态性:base、new、override、virtual 91                        //因为使用了override,重写了父类的Method2方法, 
(教学思路 C#之类八)多态性:base、new、override、virtual 92                        //因为使用了base.Method1,所以在子类中会调用父类的Method1方法 
(教学思路 C#之类八)多态性:base、new、override、virtual 93                        //子类的对象s引用的Method1方法打印出的是子类的Method2方法和父类的Method1方法 
(教学思路 C#之类八)多态性:base、new、override、virtual 94                        s.Method2(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 95                        //子类中的Method2方法,因为使用了override,重写了父类的Method2方法, 
(教学思路 C#之类八)多态性:base、new、override、virtual 96                        //所以父类的对象fs引用的Method2方法打印出的是还是从子类中继承下来的Method2方法 
(教学思路 C#之类八)多态性:base、new、override、virtual 97                        //子类中只存在子类的Method2方法,结果如上. 
(教学思路 C#之类八)多态性:base、new、override、virtual 98                        fs.Method2(); 
(教学思路 C#之类八)多态性:base、new、override、virtual 99                        //父类中的Method方法不变 
(教学思路 C#之类八)多态性:base、new、override、virtual100                        f.Method2(); 
(教学思路 C#之类八)多态性:base、new、override、virtual101                        Console.WriteLine("---------"); 
(教学思路 C#之类八)多态性:base、new、override、virtual102                } 
(教学思路 C#之类八)多态性:base、new、override、virtual103        }
 
 
结果如下:
我是子类中的Method方法,使用new关键字,显式的隐藏父类中的同名方法
我是父类中的Method方法
我是父类中的Method方法
---------
我是子类中的Method1方法,覆盖父类中的同名方法,此时S中没有了父类中Method1方法
我是子类中的Method1方法,覆盖父类中的同名方法,此时S中没有了父类中Method1方法
我是父类中的Method1方法
---------
我是子类中的Method2,覆盖父类中的同名方法,调用base.method1
我是父类中的Method1方法

我是子类中的Method2,覆盖父类中的同名方法,调用base.method1
我是父类中的Method1方法

我是父类中的Method2方法
---------
请按任意键继续. . .
         在Method2方法中我写base.Method1(),就想告诉大家,base关键字可以调用出父类所能继承到子类的任何一个成员,同学们课下也可以试一试下面两种情况:一,如果父类使用virtual,子类使用new,建立第4种Method4方法,也同样执行这三种对象调用Method4,结果应该和Method方法一致的。还是印证了我说过的当子类中用new时,无论父类是虚方法还是普通方法,都会隐藏父类方法。二,如果同学在子类中只出现override关键字,而父类中没有virtual相呼应,编译器是会报错的。
        相信通过这个实例大家应该会应用这四个关键字了,可以有的同学还是不明白父类用子类来实现的方式,没关系!用我说的爸爸到儿子家的例子仔细想想就能明白了,这种用法最常见的形式就是当抽象类和接口要实例成对象的时候,都是采用子类来实现的,我们下节课会讲到。
本文转自叶子文文博客51CTO博客,原文链接http://blog.51cto.com/leafwf/185718如需转载请自行联系原作者

叶子文文