博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

小天:上面你说了个用new可以隐藏基类方法,这个怎么说?

老田:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。隐藏继承的成员时,该成员的派生版本将替换基类版本。虽然可以在不使用 new 修饰符的情况下隐藏成员,但会生成警告。如果使用 new 显式隐藏成员,则会取消此警告,并记录要替换为派生版本这一事实。

小天:哦,明白了,也就是说用virtual修饰的成员还是存在的,只是成为了多态中的一种“态”。而使用new关键字则实实在在是将基类的方法给替换掉了,对吧?

老田:是的,若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并使用 new 修饰符修饰该成员。例如:

    public class BaseC

    {

        public int x;

        public void Invoke()

        {

            //方法体

        }

    }

    public class DerivedC : BaseC

    {

        new public void Invoke()  //尝试将new关键字的位置换换玩吧

        {

            //方法体

        }

    }

在此示例中,DerivedC.Invoke 隐藏了 BaseC.Invoke。字段 x 不受影响,因为它没有被类似名称的字段隐藏。

通过继承隐藏名称采用下列形式之一:

·         引入类或结构中的常数、指定、属性或类型隐藏具有相同名称的所有基类成员。

·         引入类或结构中的方法隐藏基类中具有相同名称的属性、字段和类型。同时也隐藏具有相同签名的所有基类方法。

·         引入类或结构中的索引器将隐藏具有相同名称的所有基类索引器。

对同一成员同时使用 new override 是错误的做法,因为这两个修饰符的含义互斥。new 修饰符会用同样的名称创建一个新成员并使原始成员变为隐藏的。override 修饰符会扩展继承成员的实现。

VS中编写代码的时候,如果不隐藏继承成员的声明中使用 new 修饰符将会生成警告。

小天:这个和虚方法有什么不同?

老田:这个就不解释了,下面这个实例:注意一定要用断点调试模式,一行行的看下编译器是怎么找到具体执行方法的,看完或许你就懂了。

    //基类 A

    public class A

    {

        public virtual void prinf()

        {

            Console.WriteLine("这是虚方法");

        }

    }

    //基类  B

    public class B : A   

    {

        public override void prinf()  //使用override重写基类方法

        {

            Console.WriteLine("这是新的方法");

        }

    }

    //基类  C

    public class C : A

    {

        public new void prinf()  //使用new 修饰符隐藏基类方法

        {

            Console.WriteLine("这是另一个新的方法");

        }

    }

 

    //本例是一个控制台应用程序,用于演示如何使用上面的类

    class Program

    {

        static void Main(string[] args)

        {

            A a1 = new B();

            A a2 = new C();

            B b1 = (B)a1;

            C c1 = (C)a2;

            a1.prinf(); //结果显示为  这是新的方法

            a2.prinf(); //结果显示为  这是虚方法

            b1.prinf(); //结果显示为  这是新的方法

            c1.prinf(); //结果显示为  这是另一个新的方法

 

            Console.ReadLine();

        }

    }

小天:哦,明白了,原来当调用一个对象的函数时,系统会直接去检查这个对象申明定义的类(等号前面的类),即申明类,看所调用的函数是否为虚函数。如果不是虚函数,那么它就直接执行该函数。而如果有virtual关键字,也就是一个虚函数,那么这个时候它就不会立刻执行该函数了,而是转去检查对象的实例类(等号后面的类)。

但是对于new函数则是直接在申明类中找到方法就执行。

本文章为天轰穿原创作品,转载请注明出处及作者。