C# 虚方法、非虚方法、重写override、new,具体调用哪个方法分析

首先先看override和new的语法特征:

    • override
      1. override是派生类用来重写基类中方法的;
      2. override不能重写非虚方法和静态方法
      3. override只能重写用virtual、abstract、override修饰的方法;
      4. 不能使用修饰符 new、static、virtual 或 abstract 来修改 override 方法。
      new
      1. new是派生类用来隐藏基类中的方法的;也就是说在派生类中“看不到”基类中的方法;
      2. 如果要在派生类中隐藏(不是重写)基类中的方法,而没有使用new关键字,编译时会出现一个警告,提示如果是要隐藏基类中的方法,请使用new关键字【默认是new修饰的】;
      3. 派生类可以隐藏基类中的虚方法,也可以隐藏基类中的普通方法。
      4. 如果在派生类中用private来修饰new 方法,那么只在该派生类中隐藏了基类中的方法,在该派生类之外,相当于没有隐藏基类中的方法;
      5. 如果在派生类中隐藏了基类中的方法,在该派生类的派生类中,将延续对该派生类对基类方法的隐藏。

测试结论:

  • 经测试:只有类中有虚方法重写override,才会表现出运行时类型方法特征其他无论是不是虚方法,是不是有new 修饰,是不是有override 修饰,都表现出编译时类型方法特征【即声明的类型是什么就调用什么方法】。

以下是测试方法内容:

//1、虚方法重写override,运行时类型方法特征。
//1.1、虚方法未重写,编译时【未重写派生类调用基类方法】产生装箱或转型
//1.2、虚方法重写new或没有new也没有override,编译时【重写派生类隐藏基类方法】
//2、非虚方法重写。编译时【重写派生类隐藏基类方法】
//3、非虚方法未重写,调用基类方法。编译时【未重写派生类调用基类方法】产生装箱或转型

 

 

 代码

 1     public class TestShape
 2     {
 3         public static void Main(string[] args)
 4         {
 5             //主要测试:1、虚方法重写override,运行时类型方法特征。
 6             //1.1、虚方法未重写,编译时【未重写派生类调用基类方法】装箱或转型
 7             //1.2、虚方法重写new或没有new也没有override,编译时【重写派生类隐藏基类方法】
 8             //2、非虚方法重写。编译时【重写派生类隐藏基类方法】
 9             //3、非虚方法未重写,调用基类方法。编译时【未重写派生类调用基类方法】装箱或转型
10 
11             //1、
12             Shape shape = new Circle();
13             shape.MethodVirtual();//circle override MethodVirtual
14             //2、编译时
15             Diamond diamond = new Diamond();
16             diamond.Method();//Diamond default Method
17             Shape s = new Diamond();
18             s.Method();//base Method call
19             //结论:非虚方法重写编译时 类型方法。
20             //1.2 编译时
21             diamond.MethodVirtual();//Diamond default MethodVirtual,没有使用override默认是new
22             s.MethodVirtual();//base MethodVirtual call,没有使用override默认是new
23             //3、编译时
24             Circle circle = new Circle();
25             circle.Method();//base Method call
26         }
27     }
28     public class Shape
29     {
30         public virtual void MethodVirtual()
31         {
32             Console.WriteLine("base MethodVirtual call");
33         }
34         public void Method()
35         {
36             Console.WriteLine("base Method call");
37         }
38     }
39     public class Circle: Shape
40     {
41         public override void MethodVirtual()
42         {
43             Console.WriteLine("circle override MethodVirtual");
44         }
45     }
46     public class Triangle : Shape
47     {
48         public new  void MethodVirtual()
49         {
50             Console.WriteLine("Triangle new MethodVirtual");
51         }
52         public new void Method()
53         {
54             Console.WriteLine("Triangle new Method");
55         }
56     }
57     public class Diamond : Shape
58     {
59         //默认是使用了new关键字
60         public void MethodVirtual()
61         {
62             Console.WriteLine("Diamond default MethodVirtual");
63         }
64         public void Method()
65         {
66             Console.WriteLine("Diamond default Method");
67         }
68     }
View Code

语言对比

Java——默认虚方法

默认情况下,Java中的方法都是虚方法。假如希望方法具有非虚的行为,就必须显式密封它。相反,C#的方法默认为非虚方法

源码,是痛苦的,又是快乐的,如果没有这痛苦,也就没有了这快乐!
原文地址:https://www.cnblogs.com/erlongxizhu-03/p/12993830.html