• 关于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的~

  • 相关阅读:
    从 PHP 到 Java
    用Lua定制Redis命令
    见招拆招-PostgreSQL中文全文索引效率优化
    通过2-3-4树理解红黑树
    代码迁移之旅(二)- 渐进式迁移方案
    多线程编程
    Gotorch
    使用PostgreSQL进行中文全文检索
    代码重构之旅(一) 项目结构
    Linux“体检”指标
  • 原文地址:https://www.cnblogs.com/brt3/p/9744070.html
Copyright © 2020-2023  润新知