C# 中,可以如下定义:
Base father = new Derived();
father 是基类引用,指向子类对象,这一点有点类似C++。
该引用的使用模式如下(先说结论)——
- father引用 可以调用所有 非virtual方法(废话);
- father 会自动调用子类 override方法(多态);
- father 无法调用子类新增的方法;
- 对于子类与父类同名但非override的方法,需要添加new关键字。这时调用是根据 father 的类型确定;
测试代码如下:
using logging; class Base{ public virtual void show(){ Log.print("method of Base::show()"); } public virtual void show2(){ Log.print("method of Base::show2()"); } public void myself(){ // without virtual. Log.print("method of Base::myself()"); } } class Derived: Base{ public override void show(){ Log.print("method of Derived::show()"); } public void show2(){ // without override, so should use 'new' Log.print("method of Derived::show2()"); } public void show3(){ // a new method Log.print("A new method of Derived."); } public void myself(){ // should use 'new' Log.print("method of Derived::myself()"); } static void Main(){ #if BASE Base t = new Derived(); #else var t = new Derived(); // same to 'Derived t = ...' #endif t.show(); t.show2(); t.show3(); // fail to compile for BASE t.myself(); } }
编译 Derived father:
$ csc tryit.cs Microsoft(R) Visual C# 编译器 版本 2.9.0.63208 (958f2354) 版权所有(C) Microsoft Corporation。保留所有权利。 tryit.cs(22,17): warning CS0114: '“Derived.show2()”隐藏继承的成员“Base.show2()”。若要使当前成员重写该实现,请添加关键字 override。否则,添加关键字 new。 tryit.cs(30,17): warning CS0108: '“Derived.myself()”隐藏继承的成员“Base.myself()”。如果是有意隐藏,请使用关键字 new。 method of Derived::show() method of Derived::show2() A new method of Derived::show3() method of Derived::myself()
编译 Base father (已注释 t.show3() 调用,否则编译失败):
$ csc tryit.cs -define:BASE Microsoft(R) Visual C# 编译器 版本 2.9.0.63208 (958f2354) 版权所有(C) Microsoft Corporation。保留所有权利。 tryit.cs(22,17): warning CS0114: '“Derived.show2()”隐藏继承的成员“Base.show2()”。若要使当前成员重写该实现,请添加关键字 override。否则,添加关键字 new。 tryit.cs(30,17): warning CS0108: '“Derived.myself()”隐藏继承的成员“Base.myself()”。如果是有意隐藏,请使用关键字 new。 method of Derived::show() method of Base::show2() method of Base::myself()
对于 Base father = new Derived() 的形式来说,似乎是一种新老结合的方式:对于virtual方法,可以自动追寻子类的实现,而非virtual则根据Base类型决定。
实际上,这个模式与C++完全相同,测试代码如下:
// g++ ctry.cpp -std=c++11 #include <stdio.h> class Base{ public: // Base() = default; virtual void show(){ printf("method of Base::show() "); } virtual void show2(){ printf("method of Base::show2() "); } void myself(){ // without virtual. printf("method of Base::myself() "); } }; class Derived: public Base{ public: virtual void show(){ printf("method of Derived::show() "); } void show2(){ // it would be run as virtual, though not written the keyword. printf("method of Derived::show2() "); } void show3(){ printf("A new method of Derived::show3() "); } void myself(){ printf("method of Derived::myself() "); } }; int main(){ Base *father = new Derived(); father->show(); father->show2(); // father->show3(); // fail to compile. father->myself(); // call the Base::myself() delete father; }
编译,执行:
$ g++ ctry.cpp -std=c++11 $ ./a.exe method of Derived::show() method of Derived::show2() method of Base::myself()
# 请忽视 C# 对show2() 的调用,那里本应该写一个override的~