• base想到...



    base 是C#中77个(如果没有记错的话)关键字之一,在MSDN文档中列举的主要作用是两个:
    1. 调用基类上已被其他方法重写的方法。
    2. 指定创建派生类实例时应调用的基类构造函数。

    注意点:基类访问只能在构造函数、实例方法或实例属性访问器中进行,从静态方法中使用base关键字是错误的。


    对于第1点,作用十分明显,重写了父类函数,但是又需要调用父类函数的时候就需要用到了,例如下面的代码:

    using System;

    class BaseClass
    {
        
    public BaseClass()
        
    {
            Console.WriteLine(
    "[BaseClass.BaseClass] " + 
               
    "Constructor called");           
        }

        
        
    public BaseClass(int foo)
        
    {
                Console.WriteLine(
    "[BaseClass.BassClass] " +
                   
    " Argument parameter is {0}", foo.ToString());    
        }

        
        
    public virtual void PrintInfo()
        
    {
                Console.WriteLine(
    "[BaseClass.BaseClass] " + 
                    
    " PrintInfo method Invoked! ");    
        }

        
        
    }


    class DerivedClass : BaseClass
    {
        
    public DerivedClass() : base(100)
        
    {
            Console.WriteLine(
    "This");    
        }

        
        
    public DerivedClass(int foo) : this()
        
    {        
            Console.WriteLine(
    "[DerivedClass.Derived] " +
                 
    "Constructor called");
        }

        
        
    public override void PrintInfo()
    //        public void PrintInfo()
        {
    //        base.PrintInfo();
                Console.WriteLine("[DerivedClass.Derived] " +
                     
    " PrintInfo method Invoked!!!");    
        }

    }


    class DefaultInitializer
    {
        
    public static void Main()
        
    {
            Console.WriteLine(
    "[Main] Instantiating a " +
               
    "DerivedClass object");
            DerivedClass derived 
    = new DerivedClass(100);
            derived.PrintInfo();
        }

    }
            

    结果和作用都是大家预期的。

    用ildasm来看一下,这个过程在IL代码中是如何进行的?

    调用override的函数,是指回去父类中去的,但是调用的代码效果却又不是父类中的代码,呵呵~~

    而在没有override时候呢, 则是这样的:


    重写后的函数调用父类在增加了base.PrintInfo();后在IL可以看到,其实它是直接调用父类中函数的:
    增加了base.PrintInfo();后:


    没有增加:


    可见重写函数中是直接调用父类对应函数的。

    两层类结构的IL代码如此,那么三层呢?IL出现的是最上层的类调用还是父类调用呢?
    用下面的代码:

    using System;

    class BaseClass
    {
        
    public BaseClass()
        
    {
            Console.WriteLine(
    "[BaseClass.BaseClass] " + 
               
    "Constructor called");           
        }

        
        
    public BaseClass(int foo)
        
    {
                Console.WriteLine(
    "[BaseClass.BassClass] " +
                   
    " Argument parameter is {0}", foo.ToString());    
        }

        
        
    public virtual void PrintInfo()
        
    {
                Console.WriteLine(
    "[BaseClass.BaseClass] " + 
                    
    " PrintInfo method Invoked! ");    
        }

        
        
    }


    class DerivedClass : BaseClass
    {
        
    public DerivedClass() : base(100)
        
    {
            Console.WriteLine(
    "This");    
        }

        
        
    public DerivedClass(int foo) : this()
        
    {        
            Console.WriteLine(
    "[DerivedClass.Derived] " +
                 
    "Constructor called");
        }

        
        
    public override void PrintInfo()
    //        public void PrintInfo()
        {
            
    base.PrintInfo();
                Console.WriteLine(
    "[DerivedClass.Derived] " +
                     
    " PrintInfo method Invoked!!!");    
        }

    }


    class DerivedClass2 : DerivedClass
    {
        
    public DerivedClass2() : base(100)
        
    {
            Console.WriteLine(
    "This");    
        }

        
        
    public DerivedClass2(int foo) : this()
        
    {        
            Console.WriteLine(
    "[DerivedClass.Derived] " +
                 
    "Constructor called");
        }

        
        
    public override void PrintInfo()
    //        public void PrintInfo()
        {
            
    base.PrintInfo();
                Console.WriteLine(
    "[DerivedClass2.Derived] " +
                     
    " PrintInfo method Invoked222!!!");    
        }

    }


    class DefaultInitializer
    {
        
    public static void Main()
        
    {
            Console.WriteLine(
    "[Main] Instantiating a " +
               
    "DerivedClass object");
            DerivedClass2 derived 
    = new DerivedClass2(100);
            derived.PrintInfo();
        }

    }
            



           从IL代码看到,它依然指向了最高层次的那个父类的。但如果此时增加base.PrintInfo()代码,却依然如我们希望的那样只是调用父类DerivedClass2的相关函数。

    重写父类一般的函数的这种方式到了IL这个层面的原来是如此的,是否和想象中的不同?




           对于第2种情况,当父类的构造函数需要带参数的,且情况比较复杂时候,用base来显式说明具体调用需要的构造函数是十分方便的,如果不特别指定则缺省调用不带参数的那个,如果父类没有这个不带参数的构造函数则会出错的。代码如上面的例子也可见一斑。

           问题是如果希望和一般函数重写那样,到子类的构造函数完全不需要父类的构造函数方式呢?构造函数似乎不可以写成override的方式的。

           想到增加一个决定父类如何构造的参数,父类根据子类传入的参数来决定如何初始化,但是这样初始化最终决定权还是在父类那边,代码如下:

    using System;

    enum ClassType
    {
        NoneInit,
        Init1,
        Init2
    }


    class BaseClass
    {

        
    public BaseClass(ClassType aType)
        
    {
               
    switch(aType)
               
    {
                  
    case ClassType.NoneInit:
                     
    break;
                  
    case ClassType.Init1:
                     
    break;
                  
    case ClassType.Init2:
                     
    break;
                  
    default:                 
                     
    break;    
               }

        }

    }

        
           有没有象override那样的实现机制呢,继承的子类比较灵活,即使有改动对父类更改也不多?


     

  • 相关阅读:
    mysql关联查询
    MySQL数据库面试题(转发来自https://thinkwon.blog.csdn.net/article/details/104778621)
    iview + vue + thinphp5.1 源码
    <!--标签嵌套规则-->
    PHP的基本变量检测方法
    PHP的八种变量
    php变量命名规范
    C++11新特性-常用
    算法设计-DP常见问题及解题技巧
    Web开发-概述
  • 原文地址:https://www.cnblogs.com/windsails/p/57794.html
Copyright © 2020-2023  润新知