简体   繁体   中英

Difference between new and override

Wondering what the difference is between the following:

Case 1: Base Class

public void DoIt();

Case 1: Inherited class

public new void DoIt();

Case 2: Base Class

public virtual void DoIt();

Case 2: Inherited class

public override void DoIt();

Both case 1 and 2 appear to have the same effect based on the tests I have run. Is there a difference, or a preferred way?

The override modifier may be used on virtual methods and must be used on abstract methods. This indicates for the compiler to use the last defined implementation of a method. Even if the method is called on a reference to the base class it will use the implementation overriding it.

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public override void DoIt()
    {
    }
}

Base b = new Derived();
b.DoIt();                      // Calls Derived.DoIt

will call Derived.DoIt if that overrides Base.DoIt .

The new modifier instructs the compiler to use your child class implementation instead of the parent class implementation. Any code that is not referencing your class but the parent class will use the parent class implementation.

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public new void DoIt()
    {
    }
}

Base b = new Derived();
Derived d = new Derived();

b.DoIt();                      // Calls Base.DoIt
d.DoIt();                      // Calls Derived.DoIt

Will first call Base.DoIt , then Derived.DoIt . They're effectively two entirely separate methods which happen to have the same name, rather than the derived method overriding the base method.

Source: Microsoft blog

virtual : indicates that a method may be overriden by an inheritor

override : overrides the functionality of a virtual method in a base class, providing different functionality.

new : hides the original method (which doesn't have to be virtual), providing different functionality. This should only be used where it is absolutely necessary.

When you hide a method, you can still access the original method by up casting to the base class. This is useful in some scenarios, but dangerous.

In the first case you are hiding the definition in the parent class. This means that it will only be invoked when you are dealing with the object as the child class. If you cast the class to its parent type, the parent's method will be invoked. In the second instance, the method is overridden and will be invoked regardless of whether the object is cast as the child or parent class.

  • new means respect your REFERENCE type(left-hand side of = ) , thereby running reference types's method. If redefined method doesn't have new keyword, it is behaved as it has. Moreover, it also known as non-polymorphic inheritance . That is, “I'm making a brand new method in the derived class that has absolutely nothing to do with any methods by the same name in the base class.” - by said Whitaker
  • override , which must be used with virtual keyword in its base class, means respect your OBJECT type(right-hand side of = ), thereby running method overriden in regardless of reference type. Moreover, it also known as polymorphic inheritance .

My way to bear in mind both keywords that they are opposite of each other.

override : virtual keyword must be defined to override the method. The method using override keyword that regardless of reference type(reference of base class or derived class) if it is instantiated with base class, the method of base class runs. Otherwise, the method of derived class runs.

new : if the keyword is used by a method, unlike override keyword, the reference type is important. If it is instantiated with derived class and the reference type is base class, the method of base class runs. If it is instantiated with derived class and the reference type is derived class, the method of derived class runs. Namely, it is contrast of override keyword. En passant, if you forget or omit to add new keyword to the method, the compiler behaves by default as new keyword is used.

class A 
{
    public string Foo() 
    {
        return "A";
    }

    public virtual string Test()
    {
        return "base test";
    }
}

class B: A
{
    public new string Foo() 
    {
        return "B";
    }
}

class C: B 
{
    public string Foo() 
    {
        return "C";
    }

    public override string Test() {
        return "derived test";
    }
}

Call in main:

A AClass = new B();
Console.WriteLine(AClass.Foo());
B BClass = new B();
Console.WriteLine(BClass.Foo());
B BClassWithC = new C();
Console.WriteLine(BClassWithC.Foo());

Console.WriteLine(AClass.Test());
Console.WriteLine(BClassWithC.Test());

Output:

A
B
B
base test
derived test

New code example,

Play with code by commenting in one-by-one.

class X
{
    protected internal /*virtual*/ void Method()
    {
        WriteLine("X");
    }
}
class Y : X
{
    protected internal /*override*/ void Method()
    {
        base.Method();
        WriteLine("Y");
    }
}
class Z : Y
{
    protected internal /*override*/ void Method()
    {
        base.Method();
        WriteLine("Z");
    }
}

class Programxyz
{
    private static void Main(string[] args)
    {
        X v = new Z();
        //Y v = new Z();
        //Z v = new Z();
        v.Method();
}

try following: (case1)

((BaseClass)(new InheritedClass())).DoIt()

Edit: virtual+override are resolved at runtime (so override really overrides virtual methods), while new just create new method with the same name, and hides the old, it is resolved at compile time -> your compiler will call the method it 'sees'

The difference between the two cases is that in case 1, the base DoIt method does not get overridden, just hidden. What this means is that depending on the type of the variable depends on which method will get called. For example:

BaseClass instance1 = new SubClass();
instance1.DoIt(); // Calls base class DoIt method

SubClass instance2 = new SubClass();
instance2.DoIt(); // Calls sub class DoIt method

This can be really confusing and results in non expected behaviour and should be avoided if possible. So the preferred way would be case 2.

In case 1 if you used call the DoIt() method of the inherited class while the type is declared as the base class you will see the action of the base class even.

/* Results
Class1
Base1
Class2
Class2
*/
public abstract class Base1
{
    public void DoIt() { Console.WriteLine("Base1"); }
}
public  class Class1 : Base1 
{
    public new void DoIt() { Console.WriteLine("Class1"); }
}
public abstract class Base2
{
    public virtual void DoIt() { Console.WriteLine("Base2"); }
}
public class Class2 : Base2
{
    public override void DoIt() { Console.WriteLine("Class2"); }
}
static void Main(string[] args)
{
    var c1 = new Class1();
    c1.DoIt();
    ((Base1)c1).DoIt();

    var c2 = new Class2();
    c2.DoIt();
    ((Base2)c2).DoIt();
    Console.Read();
}

I had the same question and it's really confusing, you should consider that override and new keywords working only with objects of type base class and value of derived class. In this case only you'll see the effect of override and new: So if you have class A and B , B inherits from A , then you instantiate an object like this:

A a = new B();

Now on calling methods will take its state into consideration. Override : means that it extends the function of the method, then it uses the method in the derived class, whereas new tell the compiler to hide the method in the derived class and use the method in the base class instead. Here is a very good sight to that subject:

https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396

The article below is in vb.net but I think the explanation about new vs overrides is very easy to grasp.

https://www.codeproject.com/articles/17477/the-dark-shadow-of-overrides

At some point in the article, there is this sentence:

In general, Shadows assumes the function associated with the type is invoked, while Overrides assumes the object implementation is executed.

The accepted answer to this question is perfect but I think this article provide good examples to add better meaning about the differences between these two keywords.

If keyword override is used in derive class then its override the parent method.

If Keyword new is used in derive class then derive method hided by parent method.

Out of all those, new is the most confusing. Through experimenting, the new keyword is like giving developers the option to override the inheriting class implementation with the base class implementation by explicitly defining the type. It is like thinking the other way around.

In the example below, the result will return "Derived result" until the type is explicitly defined as BaseClass test, only then "Base result" will be returned.

class Program
{
    static void Main(string[] args)
    {
        var test = new DerivedClass();
        var result = test.DoSomething();
    }
}

class BaseClass
{
    public virtual string DoSomething()
    {
        return "Base result";
    }
}

class DerivedClass : BaseClass
{
    public new string DoSomething()
    {
        return "Derived result";
    }
}

在此处输入图片说明

All combinations of none, virtual, override, new and abstract:

The functional difference will not be show in these tests:

BaseClass bc = new BaseClass();

bc.DoIt();

DerivedClass dc = new DerivedClass();

dc.ShowIt();

In this exmample, the Doit that is called is the one you expect to be called.

In order to see the difference you have to do this:

BaseClass obj = new DerivedClass();

obj.DoIt();

You will see if you run that test that in the case 1 (as you defined it), the DoIt() in BaseClass is called, in case 2 (as you defined it), the DoIt() in DerivedClass is called.

At the first case it will call derived class DoIt() method because new keyword hides base class DoIt() method.

At the second case it will call overriden DoIt()

  public class A
{
    public virtual void DoIt()
    {
        Console.WriteLine("A::DoIt()");
    }
}

public class B : A
{
    new public void DoIt()
    {
        Console.WriteLine("B::DoIt()");
    }
}

public class C : A
{
    public override void DoIt()
    {
        Console.WriteLine("C::DoIt()");
    }
}

let create instance of these classes

   A instanceA = new A();

    B instanceB = new B();
    C instanceC = new C();

    instanceA.DoIt(); //A::DoIt()
    instanceB.DoIt(); //B::DoIt()
    instanceC.DoIt(); //B::DoIt()

Everything is expected at above. Let set instanceB and instanceC to instanceA and call DoIt() method and check result.

    instanceA = instanceB;
    instanceA.DoIt(); //A::DoIt() calls DoIt method in class A

    instanceA = instanceC;
    instanceA.DoIt();//C::DoIt() calls DoIt method in class C because it was overriden in class C

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM