在类的继承和多态中对实例化顺序和方法重写用法的一些总结
总结一下使用类继承和多态时,实例化顺序以及方法继承重写中new,virtual、abstract、override的用法和规则:
继承关系:实例化对象时,作用类型范围在最初基类到具体实例对象的类之间(中间包括父类子类,成员访问权限:private、protected、public):
1、 子类实例构造器必须指定拥有父类访问权限的实例构造器:base(xxx),不写默认父类无参构造器;使用:this(xxx)指定先运行本类的某实例构造器,再由他指定执行的父类实例构造器;
2、 先实例化基类,再实例化子类,再子类的子类....最后到要实例的类(实例构造函数执行顺序先父后子...;期间加载时遇到有静态构造器就会先运行静态构造器,再到指定的实例构造器按顺序规则执行,静态构造器只在加载时执行一次,执行过就会跳过);
3、 在运行方法时,就运行当前所属类型中的方法:
1).当遇到隐藏new方法时(实际上C#中使用签名隐藏,只要方法名字和参数相同就会隐藏而new只是消除编译器警告罢了),说明子类方法为全新方法与父类不具重写关系,仍然运行当前所属类型中的方法;
2).当遇到虚virtual、抽象abstract、继承覆盖override方法时,说明方法具体实现已重写,就运行离具体对象类型关系最近的一个类的重写方法。当然关系最近的是自身。
最后例子说明一下:
这里提一下:抽象类无法直接实例化即不能显式调用构造器(new,反射),需要借助子类实例化时,构造函数调用抽象类的构造函数如:base()进行实例化,就是为继承和重写而生的;抽象实例成员只能放在抽象类中;静态类只能有静态成员(包括构造函数),不能显式调用构造器,初始加载时系统通过构造函数自动创建一个静态对象。
1 public abstract class A 2 { 3 public int x; 4 public A() 5 { 6 x = -1; 7 Console.WriteLine("x={0}", x); 8 Print1(); 9 Print2(); 10 } 11 public virtual void Print1() 12 { 13 x = 1; 14 Console.WriteLine("x={0}", x); 15 } 16 17 public virtual void Print2() 18 { 19 x = 2; 20 Console.WriteLine("x={0}", x); 21 } 22 } 23 24 public class B : A 25 { 26 public int y; 27 public B() 28 { 29 y = -1; 30 Console.WriteLine("x={0},y={1}", x, y); 31 Print1(); 32 Print2(); 33 } 34 35 public override void Print1() 36 { 37 x = 3; 38 y = 1; 39 Console.WriteLine("x={0},y={1}", x, y); 40 } 41 //该方法将继承的重新创建,自身及其后子类重写均为这个方法 42 public new virtual void Print2() 43 { 44 x = 4; 45 y = 2; 46 Console.WriteLine("x={0},y={1}", x, y); 47 } 48 } 49 public class C : B 50 { 51 //该方法将继承的重新创建,自身及其后子类继承的均为这个方法 52 public new void Print1() 53 { 54 x = 5; 55 y = 3; 56 Console.WriteLine("x={0},y={1}", x, y); 57 } 58 //该方法重写自父类B,而不是基类A 59 public override void Print2() 60 { 61 x = 4; 62 y = 2; 63 Console.WriteLine("x={0},y={1}", x, y); 64 } 65 } 66 public static class D 67 { 68 public static string _name; 69 static D() 70 { 71 _name = "小明"; 72 } 73 }
主程序:
1 static void Main(string[] args) 2 { 3 A c = new C(); 4 c.Print1(); 5 c.Print2(); 6 //静态、抽象类反射不能创建 7 //Type type = typeof(A); 8 //var constructor = type.GetConstructor(Type.EmptyTypes); 9 //Object obj = constructor.Invoke(null); 10 //Console.WriteLine(obj.GetType().Name); 11 //Type type = typeof(D); 12 //var constructor = type.GetConstructor(BindingFlags.Static|BindingFlags.NonPublic,null,Type.EmptyTypes,null); 13 //Object obj = constructor.Invoke(null); 14 //Console.WriteLine(obj.GetType().Name); 15 Console.WriteLine(D._name); 16 Console.ReadKey(); 17 } 18
输出结果: