虚方法virtual和抽象方法abstract以及多态的研究(重新整理)

虚方法virtual和抽象方法abstract以及多态的研究<14/10/2017>

虚方法virtual定义:    

当类中的方法声明前加上了 virtual 修饰符,我们称之为虚方法,反之为非虚。

使用了 virtual 修饰符后,不允许再有 static , abstract 或override 修饰符(必须是 Public )。   

为了实现多态,父类里面的方法用虚方法,子类里面可以对该方法重写,也可以不重写,当我们创建了一个子类 的对象并把它转换成了父类的类型后,如果子类里面没有重写父类里面的虚方法,则直接调用父类的方法,如果子类 里面重写了虚方法,则调用子类时面重写后的方法。

虚方法和非虚方法什么区别呢?

对于非虚的方法,无论被其所在类的实例调用,还是被这个类的派生类的实例调用,方法的执行方式不变对于虚方法它的执行方式可以被派生类改变,这种改变是通过方法的重载来实现的。举个例子(简单的代码):

	    class A  
      {  
          public void F() { Console.WriteLine("A.F"); }  
          public virtual void G() { Console.WriteLine("A.G"); }  //定义虚方法  
      }  
            class B : A  
      {  
          new public void F() { Console.WriteLine("B.F"); }      //这里的方法则不能重写,因为基类中的F()方法不是虚方法。  
          public override void G() { Console.WriteLine("B.G"); }   //重写虚方法  
     }  
            static void Main(string[] args)  
     {          
             B b = new B();  
             A a = b;      //A对象指向B对象  
             b.F();       //显示结果B.F     a(基)父b(派)子
             a.F();       //显示结果A.F  
             b.G();       //显示结果B.G   
             a.G();       //显示结果B.G 实际这里调用的是不是基类中的G方法,而是派生类中重写过的G方法。  
             Console.ReadKey();  
         }  

结果是:

B.F

A.F

B.G

B.G//***重点:当基类对象指向派生类对象时,基类的虚方法被重写,函数执行的是派生类方法。不是虚方法调用的是基类方法***//

a.G()的结果是B.G。这里了可以得出结论,当基类对象指向派生类对象时,基类的虚方法被重写,函数执行的是派生类方法。不是虚方法调用的是基类方法。

非虚拟方法的实现是不变的:无论是在声明它的类的实例上调用该方法还是在派生类的实例上调用,实现都是相同的。与此相反,虚拟方法的实现可以由派生类取代取代所继承的虚拟方法之实现的过程称为重写方法   

这里的new 是在子类对父类方法的一种替换,不写会有警告;

与抽象方法什么区别呢?

一、抽象方法的使用:
 1、方法前加abstract,同时在类前也要加abstract(必须要加),这个类称为抽象类,方法要是public。
 2、抽象方法不能实现,这里说的实现是指没有方法体,但是必须在非抽象子类里实现; 
 3、抽象方法在子类里一定要重写;
 4、任何一个非抽象子类必须要重写父类的抽象方法。
二、区别:
   1、抽象方法在父类里面一定不可以实现,即要有方法体(就是方法后面有没有大括号{ }),而虚方法在父类时面一定要带方法体(实现为空也行)
   2、抽象方法在子类里面一定要实现,虚方法在子类里面可以不用重写,也可以重写(重写要实现)。二者都可以看做多态的范畴,这些多用在设计模式上写大型的游戏时多用在搭框架。 C#中写方法的时候,除了接口和抽象方法,其它的基本都带方法体

这两者都是多态的范畴,多态怎么理解?

  多态是我们在写方法时,为了使代码的重用性达到最大,通常都会把子类的对象转换成父类,但是在调方法时只能调到父类里面的方法,而子类里面的方法调不到,但是每个子类又有各自的行为,此时用到多态,子类时面重写父类里面的方法,但子类在调同一个方法时,都会调到各自重写的方法,这样类型也达到了统一,处理起来也方便,同时也体现了子类 的各自的行为.(粗糙的说多态是和重写方法同时出现的,因为重写了就实现了多态,如果不重写,所有的子类调用父类的虚方法都是一样的,但是这样的话不要说出来,自己理解可以这样理解 ,说出来别人会认为你外行了。)
 另外接口也可以实现多态,多个类继承一个接口,各自类进行不同的实现后,不同的类调用接口里面的方法 ,这样也实现了多态。虚方法,抽象方法和接口都可以实现多态,设计模式里面大多用到接口。

 重写的概念:

是子类(即派生类)的方法覆盖父类(即基类)的虚方法。

 重写的要求:

1、三相同:

(1)方法名称相同

(2)参数列表相同

(3)返回值类型相同

一句话,只需重写代码体的内容!

2、重写声明不能更改虚方法的可访问性:重写方法和虚方法必须具有相同的访问级修饰符。例如:虚方法为public的,重新方法也必须是public的。

3、可以重写基方法:必须是虚拟的(virtual)、抽象的(abstract)或重写的(override)。(非虚方法或静态方法是不可以重写的)。

4、不能使用下列修饰符修改重写(override)方法(即该方法中含有override关键字):new、static、virtual、abstract

如:new public override void outwork () //这样写是不可以的

{

      MessageBox.Show("子类的子类(override)下班");

}

5、重写属性:重写的属性必须与继承属性有完全相同的访问修饰符、类型和属性名,并且重写属性必须是虚拟的(virtual)、抽象的(abstract)或是重写的(override)。

6、new关键字和override关键字比较:(***概念也很重要***)

        如果使用override重写xx方法,通过父类引用一样只能看到重写后的方法;override重写的是虚方法,那么就只剩下重写以后的方法,原来的方法被覆盖了。如果使用new隐藏xx方法,父类子类引用各自对应方法;new隐藏基类的方法,那么基类的方法和当前类的方法同时存在只是被隐藏了。

总结:override可以覆盖基类的方法,让基类的方法以子类的内容实现,而new不用来覆盖基类的方法,而是全新定义一个子类的方法,这个方法只属于子类,与基类的方法无关,只是名字上相同而已。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值