关于C#多态的思考

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();
    }
}
View Code

编译 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;
}
View Code

编译,执行:

$ g++ ctry.cpp -std=c++11

$ ./a.exe
method of Derived::show()
method of Derived::show2()
method of Base::myself()

# 请忽视 C# 对show2() 的调用,那里本应该写一个override的~

原文地址:https://www.cnblogs.com/brt3/p/9744070.html