zoukankan      html  css  js  c++  java
  • 关于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的~

  • 相关阅读:
    Linux----------系统管理之释放内存
    阿里云OSS挂载到ECS(注意fuse版本,必须和源码对应)
    数据库图形化管理工具navicat
    linux集群管理工具clustershell
    记一次nginx启动报错
    虚拟化之KVM
    虚拟化之-XEN(未完待续)
    虚拟化
    Linux----------Jenkins基础
    Linux日常系统管理命令
  • 原文地址:https://www.cnblogs.com/brt3/p/9744070.html
Copyright © 2011-2022 走看看