C#中Abstract和Virtual的区别

c# 中 Abstract(虚方法)Virtual (抽象方法)都与继承有关,并且涉及override的使用。两者比较容易混淆,下面讨论一下二者的区别。

一、virtual方法

  virtual 关键字用于在基类中修饰方法

  virtual的使用会有两种情况:
  情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。
  情况2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。

二、abstract方法

  abstract关键字只能用在抽象类中修饰方法,并且没有具体的实现。抽象方法的实现必须在派生类中使用override关键字来实现。
  接口和抽象类最本质的区别:抽象类是一个不完全的类,是对象的抽象;而接口是一种行为(函数、方法)规范。

三、关键字含义的比较

  static:当一个方法被声明为static时,这个方法是一个静态方法,编译器会在编译时保留这个方法的实现。也就是说,这个方法属于类,但是不属于任何成员,不管这个类的实例是否存在,它们都会存在。就像入口函数static void Main,因为它是静态函数,所以可以直接被调用。

  virtual:当一个方法被声明为virtual时,它是一个虚拟方法,直到你使用 ClassName variable = new ClassName();  明一个类的实例之前,它都不存在于真实的内存空间中。这个关键字在类的继承中非常常用,用来提供类方法的多态性支持。virtual,abstract是告诉其它想继承于他的类 你可以重写我的这个方法或属性。

  overrride:表示重写这个继承于基类的某个virtual方法。
  abstract:抽象方法声明使用,是必须被派生类覆盖的方法,抽象类就是用来被继承的;可以看成是没有实现体的虚方法。如果类中包含抽象方法,那么类就必须定义为抽象类,不论是否还包含其他一般方法;抽象类不能被直接被创建为对象实体的。

四、重写和覆盖

重写

用关键字 virtual 修饰的方法,叫虚方法。可以在子类中用override 声明同名的方法。

相应的没有用virtual修饰的方法,我们叫它实方法。

public class C1
{
    public virtual string GetName()
    {
        return "徐明祥";
    }
}

public class C2 : C1
{
    public override string GetName()
    {
        return "xumingxiang";
    }
}

 C1 c1 = new C1();
 Console.WriteLine(c1.GetName());//输出“徐明祥”

 C2 c2 = new C2();
 Console.WriteLine(c2.GetName());//输出“xumingxiang”
 //重点看这里
 C1 c3 = new C2();
 Console.WriteLine(c3.GetName());//输出“xumingxiang”
重写Demo

覆盖

在子类中用 new 关键字修饰 定义的与父类中同名的方法

覆盖不会改变父类方法的功能。

public class C1
{
    public string GetName()
    {
        return "徐明祥";
    }
}

public class C2 : C1
{
    public new string GetName()
    {
        return "xumingxiang";
    }
}

C1 c1 = new C1();
Console.WriteLine(c1.GetName());//输出“徐明祥”

C2 c2 = new C2();
Console.WriteLine(c2.GetName());//输出“xumingxiang”
//重点看这里,和上面的重写作比较
C1 c3 = new C2();
Console.WriteLine(c3.GetName());//输出“徐明祥”
覆盖Demo

说明:

当用父类装箱子类对象时,如 C1 c3 = new C2():重写会改变父类该函数委托链(和指针数组类似)的指向,即调用子类的该重写后的函数;而覆盖不会,仍然调用父类的函数。

关于重写和覆盖的使用:重写使用的频率比较高,实现多态; 覆盖用的频率比较低,如对以前无法修改的类进行继承的情景。

抽象方法虚方法接口,可以被重写(override);实方法不可以。

虚、实方法都可以被覆盖(new);而抽象方法,接口 不可以。

参考文章

C#中Abstract和Virtual的区别,主要内容出处。

C#中的重写和覆盖的区别诺-诺,15-8。

更多相关阅读,请参考本人文章 C# 类的多态、结构、接口、抽象、虚函数总结

 

原文地址:https://www.cnblogs.com/arxive/p/7809619.html