• 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# 类的多态、结构、接口、抽象、虚函数总结

     

  • 相关阅读:
    Spring配置通过动态工厂方法创建的bean
    Spring配置通过静态工厂方法创建的bean
    SpringMVC针对post请求乱码的处理
    SpringMVC的HelloWorld快速入门!
    SpringMVC和Spring的关系
    pageContext、request、session和application区别
    orcale 实现 sql server 里面的表值函数SPLIT
    查询语句有 or 会导致查询速度变慢问题解决
    用谷歌浏览器以及插件 测试接口
    OraCle 记录 实现 sql中的 for xml path ('')
  • 原文地址:https://www.cnblogs.com/arxive/p/7809619.html
Copyright © 2020-2023  润新知