• abstract、virtual、override 和 new


     abstract、virtual、override 和 new 是在类的继承关系中常用的四个修饰方法的关键字,在此略作总结。

    1. 常用的中文名:abstract 抽象方法,virtual 虚方法,override 覆盖基类方法,new 隐藏基类方法,override 和 new 有时都叫重写基类方法。

    2. 适用场合:abstract 和 virtual 用在基类(父类)中;override 和 new 用在派生类(子类)中。

    3. 具体概念:

        abstract 抽象方法,是空方法,没有方法体,派生类必须以 override 实现此方法。

        virtual 虚方法,若希望或预料到基类的这个方法在将来的派生类中会被重写(override 或 new),则此方法必须被声明为 virtual。

        override 重写继承自基类的 virtural 方法,可以理解为拆掉老房子,在原址上建新房子,老房子再也找不到了(基类方法永远调用不到了)。

        new 隐藏继承自基类的 virtual 方法,老房子还留着,在旁边盖个新房,想住新房住新房(作为派生类对象调用),想住老房住老房(作为基类对象调用)。

        当派生类中出现与基类同名的方法,而此方法前面未加 override 或 new 修饰符时,编译器会报警告,但不报错,真正执行时等同于加了 new。

    4. abstract 和 virtual 的区别:abstract 方法还没实现,连累着基类也不能被实例化,除了作为一种规则或符号外没啥用;virtual 则比较好,派生类想重写就重写,不想重写就吃老子的。而且继承再好也是少用为妙,继承层次越少越好,派生类新扩展的功能越少越好,virtual 深合此意。

    5. override 和 new 的区别:当派生类对象作为基类类型使用时,override 的执行派生类方法,new 的执行基类方法。如果作为派生类类型调用,则都是执行 override 或 new 之后的。


    演示 override 和 new 区别的例子:


    // Define the base class
    class Car
    {
       
    public virtual void DescribeCar()
       {
           System.Console.WriteLine(
    "Four wheels and an engine.");
       }
    }

    // Define the derived classes
    class ConvertibleCar : Car
    {
       
    public new virtual void DescribeCar()
       {
           
    base.DescribeCar();
           System.Console.WriteLine(
    "A roof that opens up.");
       }
    }
    class Minivan : Car
    {
       
    public override void DescribeCar()
       {
           
    base.DescribeCar();
           System.Console.WriteLine(
    "Carries seven people.");
       }
    }
    public static void TestCars1()
    {
       Car car1 
    = new Car();
       car1.DescribeCar();
       System.Console.WriteLine(
    "----------");

       ConvertibleCar car2 
    = new ConvertibleCar();
       car2.DescribeCar();
       System.Console.WriteLine(
    "----------");

       Minivan car3 
    = new Minivan();
       car3.DescribeCar();

       System.Console.WriteLine("----------");

    }

     

    输出类似如下所示:

    Four wheels and an engine.

    ----------

    Four wheels and an engine.

    A roof that opens up.

    ----------

    Four wheels and an engine.

    Carries seven people.

    ----------

    但是,如果我们声明一个从 Car 基类派生的对象的数组。此数组能够存储 Car、ConvertibleCar 和 Minivan 对象,如下所示:


    public static void TestCars2()
    {
        Car[] cars 
    = new Car[3];
        cars[
    0= new Car();
        cars[
    1= new ConvertibleCar();

        cars[2] = new Minivan();

    }

     

    然后用一个 foreach 循环来访问该数组中包含的每个 Car 对象,并调用 DescribeCar 方法,如下所示:


    foreach (Car vehicle in cars)
    {
      System.Console.WriteLine(
    "Car object: " + vehicle.GetType());
      vehicle.DescribeCar();

      System.Console.WriteLine("----------");

    }

     

    此循环的输出如下所示:

    Car object: YourApplication.Car

    Four wheels and an engine.

    ----------

    Car object: YourApplication.ConvertibleCar

    Four wheels and an engine.

    ----------

    Car object: YourApplication.Minivan

    Four wheels and an engine.

    Carries seven people.

    ----------

    注意,ConvertibleCar 的说明可能与您的预期不同。由于使用了 new 关键字来定义此方法,所调用的不是派生类方法,而是基类方法。Minivan 对象正确地调用重写方法,并产生预期的结果。

  • 相关阅读:
    C#关键字
    委托
    async和await异步编程
    IOC、DI,IoC容器
    数据库脏读、幻读
    关于vue 从零开始的搭建注意事项
    C#.NET WebApi返回各种类型(图片/json数据/字符串)
    win7下IIS配置以及域名映射方法
    18/11月 日常总结
    Js 数组去重的几种方法总结
  • 原文地址:https://www.cnblogs.com/zjoch/p/1969626.html
Copyright © 2020-2023  润新知