zoukankan      html  css  js  c++  java
  • override和new的区别

     

    override

    1. override是派生类用来重写基类中方法的;

    2. override不能重写非虚方法和静态方法;

    3. override只能重写用virtual、abstract、override修饰的方法;

    4. 不能使用修饰符 new、static、virtual 或 abstract 来修改 override 方法。

    new

    1. new是派生类用来隐藏基类中的方法的;也就是说在派生类中“看不到”基类中的方法;

    2. 如果要在派生类中隐藏(不是重写)基类中的方法,而没有使用new关键字,编译时会出现一个警告,提示如果是要隐藏基类中的方法,请使用new关键字;

    3. 派生类可以隐藏基类中的虚方法,也可以隐藏基类中的普通方法。

    4. 如果在派生类中用private来修饰new 方法,那么只在该派生类中隐藏了基类中的方法,在该派生类之外,相当于没有隐藏基类中的方法;

    5. 如果在派生类中隐藏了基类中的方法,在该派生类的派生类中,将延续对该派生类对基类方法的隐藏。

    代码:

    class A
        {
            public virtual void Func() // 注意virtual,表明这是一个虚拟函数 
            {
                Console.WriteLine("Func In A");
            }
        }
        class B : A // 注意B是从A类继承,所以A是父类,B是子类 
        {
            public override void Func() // 注意override ,表明重新实现了虚函数 
            {
                Console.WriteLine("Func In B");
            }
        }
        class C : B // 注意C是从B类继承,所以B是父类,C是子类 
        {
        }
        class D : A // 注意D是从A类继承,所以A是父类,D是子类 
        {
            public new void Func() // 注意new,表明覆盖父类里的同名类,而不是重新实现 
            {
                Console.WriteLine("Func In D");
            }
        }
        class E : D // 注意E是从D类继承,所以D是父类,E是子类 
        {
          
        }
        class F : A
        {
            private new void Func() //注意new关键字前有private修饰符,故该隐藏只在F类内有效
            {
                Console.WriteLine("Func In F");
            }
    
            public void Func2() 
            {
                Func(); //在F类内隐藏了基类的Func方法,故此处调用的private new void Func()
            }
        }
    
    
     static void Main(string[] args)
            {
                A a; // 定义一个a这个A类的对象.这个A就是a的申明类 
                A b; // 定义一个b这个A类的对象.这个A就是b的申明类 
                A c; // 定义一个c这个A类的对象.这个A就是c的申明类 
                A d; // 定义一个d这个A类的对象.这个A就是d的申明类 
                A e; // 定义一个e这个A类的对象.这个A就是e的申明类 
                A f; // 定义一个f这个A类的对象.这个A就是f的申明类 
                a = new A(); // 实例化a对象,A是a的实例类 
                b = new B(); // 实例化b对象,B是b的实例类 
                c = new C(); // 实例化c对象,C是c的实例类 
                d = new D(); // 实例化d对象,D是d的实例类 
                e = new E(); // 实例化e对象,E是e的实例类
                f = new F(); // 实例化f对象,F是f的实例类
                Console.WriteLine("a.Func();");
                a.Func(); // 执行a.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类A,就为本身 4.执行实例类A中的方法 5.输出结果 Func In A 
                Console.WriteLine("b.Func();");
                b.Func(); // 执行b.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重载的 4.执行实例类B中的方法 5.输出结果 Func In B 
                Console.WriteLine("c.Func();");
                c.Func(); // 执行c.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重载的 4.转去检查类C的父类B,有重载的 5.执行父类B中的Func方法 5.输出结果 Func In B 
                Console.WriteLine("d.Func();");
                d.Func(); // 执行d.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类D,无重载的(这个地方要注意了,虽然D里有实现Func(),但没有使用override关键字,所以不会被认为是重载) 4.转去检查类D的父类A,就为本身 5.执行父类A中的Func方法 5.输出结果 Func In A 
                Console.WriteLine("e.Func();");
                e.Func(); // 执行e.Func:E继承D,E.Func没有重写父类中的方法,相当于执行父类D中的Func方法,输出结果 Func In A 
                Console.WriteLine("f.Func();");
                f.Func(); // 执行f.Func:F类中虽然隐藏了基类中的Func方法,但是有private修饰符,该隐藏只在F类范围内有效。执行f.Func相当于执行其基类中的Func方法,输出结果 Func In A 
                
                D d1 = new D();
                Console.WriteLine("d1.Func();");
                d1.Func(); // 执行D类里的Func(),输出结果 Func In D 
    
                E e1 = new E();
                Console.WriteLine("e1.Func();");
                e1.Func(); // 执行E类里的Func(),输出结果 Func In D
    
                F f1 = new F();
                Console.WriteLine("f1.Func();");
                f1.Func(); // 执行F类里的Func(),输出结果 Func In A
                Console.WriteLine("f1.Func2();");
                f1.Func2(); // 执行F类里的Func2(),输出结果 Func In F
               
                Console.ReadLine();
            }

    花时间研究了一下overide和new的区别,但是产生了一个疑问:什么时候需要隐藏方法呢?

    1. 有人说需要hack类库。http://www.cnblogs.com/hcoona/archive/2010/07/11/1775113.html

    该文作者对这种情况也有若干疑问。

    2. 看msdn又说到了这样一种情况:

    ---------------------------------------------------------------------------------------------

    默认情况下,C# 方法不是虚方法 -- 如果将一种方法声明为虚方法,则继承该方法的任何类都可以实现其自己的版本。若要使方法成为虚方法,必须在基类的方法声明中使用 virtual 修饰符。然后,派生类可以使用 override 关键字重写基虚方法,或使用 new 关键字隐藏基类中的虚方法。如果 override 关键字和 new 关键字均未指定,编译器将发出警告,并且派生类中的方法将隐藏基类中的方法。有关更多信息,请参见编译器警告 CS0108

    为了在实践中演示上述情况,我们暂时假定公司 A 创建了一个名为 GraphicsClass 的类,您的程序使用该类。GraphicsClass 类似如下:

     
    class GraphicsClass
    {
        public virtual void DrawLine() { }
        public virtual void DrawPoint() { }
    }
    
    

    您的公司使用此类,并且您在添加新方法时将其用来派生自己的类:

     
    class YourDerivedGraphicsClass : GraphicsClass
    {
        public void DrawRectangle() { }
    }
    
    

    您在应用程序的使用过程中没有遇到任何问题,直到公司 A 发布了 GraphicsClass 的新版本,该新版本类似如下:

     
    class GraphicsClass
    {
        public virtual void DrawLine() { }
        public virtual void DrawPoint() { }
        public virtual void DrawRectangle() { }
    }
    
    

    现在,GraphicsClass 的新版本中包含了一个称为 DrawRectangle 的方法。最初,一切正常。新版本仍与旧版本二进制兼容 -- 即使在计算机系统中安装新类,部署的所有软件仍将继续工作。在您的派生类中,对方法 DrawRectangle 的任何现有调用将继续引用您的版本。

    但是,一旦使用 GraphicsClass 的新版本重新编译应用程序,您将收到来自编译器的警告。有关更多信息,请参见编译器警告 CS0108

    此警告提示您需要考虑您的 DrawRectangle 方法在应用程序中的工作方式。

    如果想用您的方法重写新的基类方法,请使用 override 关键字,如下所示:

     
    class YourDerivedGraphicsClass : GraphicsClass
    {
        public override void DrawRectangle() { }
    }
    
    

    override 关键字可确保派生自 YourDerivedGraphicsClass 的任何对象都将使用 DrawRectangle 的派生类版本。派生自 YourDerivedGraphicsClass的对象仍可以使用 base 关键字访问 DrawRectangle 的基类版本,如下所示:

     
    base.DrawRectangle();
    
    

    如果不想用您的方法重写新的基类方法,则应注意下面的事项。为避免在两种方法之间引起混淆,可以重命名您的方法。重命名方法可能很耗时且容易出错, 而且在某些情况下并不实用。但是,如果您的项目相对较小,则可以使用 Visual Studio 的重构选项来重命名方法。有关更多信息,请参见重构类和类型

    或者,也可以通过在派生类定义中使用关键字 new 来防止出现该警告,如下所示:

     
    class YourDerivedGraphicsClass : GraphicsClass
    {
        public new void DrawRectangle() { }
    }
    
    

    使用 new 关键字告诉编译器您的定义将隐藏基类中包含的定义。这是默认行为。

    -------------------------------------------------------------------------------------

    msdn上提到的这种情况可以理解。

    不知道是否还有别的理由需要使用new,以后慢慢研究吧。

  • 相关阅读:
    remove white space from read
    optimize the access speed of django website
    dowload image from requests
    run jupyter from command
    crawl wechat page
    python version 2.7 required which was not found in the registry windows 7
    health
    alternate rows shading using conditional formatting
    word
    【JAVA基础】static 关键字
  • 原文地址:https://www.cnblogs.com/roboot/p/5044161.html
Copyright © 2011-2022 走看看