C#语法中的virtual

来源:互联网 发布:为知笔记泄露用户笔记 编辑:程序博客网 时间:2024/04/27 05:51

 C#可以隐式地把对象转换为它的祖先类型(那么,一个Date类型的引用,可能其实引用的是一个ExtendedDate),父类可以做的任何事,子类都可以做

但是,即使一个父类的引用引用的是一个子类对象,这个引用还是不能调用子类对象的方法

一个ExtendedDate对象变量,可以声明为一个Object对象变量,这个变量的声明类型是Object,实际类型是ExtendedDate

一个变量的真实类型,总是它自己或它的子类

obj.GetType() == typeof(ExtendedDate) 这两个都返回Type类

GetType是一个实例方法,而typeof是一个操作符


子类继承父类重载方法可以用两个关键字:override, new,当override一个virtual方法时,该重写方法仍然是virtual的


用基类声明一个它子类的对象,这个时候,调用virtual方法都会调用子类继承的方法,而调用非virtual方法,还是会调用基类的方法,这些特性叫多态。

Date dt = new Date();
Console.WriteLine(dt);

Console.WriteLine没有带Date参数的重载方法,但是它有以object为参数的方法,而Date是一个object,所以会自动调用这个方法。object的toString方法被调用了。由于toString方法是virtual的,所以实际上调用了Date的toString方法。编译器在编译的时候并不知道要绑定哪个toString方法,只有在运行时,才会真正知道这个对象的类型。这叫做迟绑定。注意,一定是virtual方法才可以允许父类的引用绑定子类的方法。非virtual的方法,只能绑定声明类型的方法。
virtual的好处是,可以声明一个父类的数组,而真正调用方法时,调用不同子类各自的方法。

可以将方法声明为abstract的,一个abstract方法默认是一个virtual方法。和abstract正相反的是sealed,一个abstract的类必须被继承,而一个sealed类不能被继承。

假如声明了一个object数组,那么这个数组可以存储任何对象。甚至可以存储值类型的int, bool, decimal,甚至可以存储structure。例如:
decimal pi = 3.14159m;
object obj = pi;
但是编译器在栈上分配了16bytes的存储给pi, 编译器还给obj分配了一个引用所占的存储,通常obj是一个指向堆(存储对象的地方)的引用,但是没有new关键字,怎么在堆中分配空间呢?幕后的实现是这样的:一旦值类型被分给对象变量,就在堆中创建这个值类型的存储空间,从栈上将这个值类型拷贝到堆中。一旦这个值类型又被分配给值变量,那么堆上的存储又抽回到栈中。这种机制会影响性能。应尽量避免这样做。