开发者

Why would you want to hide a method using `new`? [duplicate]

开发者 https://www.devze.com 2023-03-30 07:15 出处:网络
This question already has answers here: Closed 11 years ago. Possible Duplicate: C# - new keyword in method signature
This question already has answers here: Closed 11 years ago.

Possible Duplicate:

C# - new keyword in method signature

Let's say I have 3 classes: GrandDad, Dad, Son. Son inherits from Dad, which inherits from GrandDad.

Each class implements foo.

// GrandDad class: 
public virtual void foo()

// Dad class: 
new public virtual void foo()

// Son class: 
public override void foo()

I don't understand the reason as to why Dad would use the new keyword开发者_Python百科. As I understand, using new hides a method. Why would you want to do this?

I read the MSDN explanation of new, but the discussion was only mechanical, rather than architectural.

Thanks


Your presented code isn't a very good example, but one general use case for 'new' is if a base class is modified to add a new method (typically a base class beyond your control), but you have existing code that needs to call your derived class method with the same name. Changing the derived class method to 'new' allows you to remain compatible with existing consumers of your public interface.


Hope below example gives you the idea for the purpose of new keyword. That's really depend on the requirement of the functionality.

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

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

...

Base b = new Derived();
b.SomeMethod();

will end up calling Derived.SomeMethod if that overrides Base.SomeMethod.

Now, if you use the new keyword instead of override, the method in the derived class doesn't override the method in the base class, it merely hides it. In that case, code like this:

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

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

...


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

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


A scenario where maybe "useful" when you have a hierarchy of classes at more layers (Control, Button, RedButton) and you want any subclass of a given class (Button) to be restricted for altering the generic behavior inherited from Control, that is modified by Button; to play by Button rules, and not by Control rules, other way the RedButton can become a TreeViewControl :) ...; This can be happen when you inherit implementation :)

There are other technics, more clean, like "strategy pattern" (you aggregate behaviour, and not inherited) are used to handle the previous scenario.


I'll give an example that goes beyond "what it does," and cover when it can be useful.

Ever needed one of your business classes to be a container? For example, perhaps you want to do this:

Person aperson = new Person();
aperson.Add(anAddress);
aperson.Add(anAddress);

If you want the Add() method to perform some business-specific logic upon insertion, you have a choice. Either you implement container functionality all your own (yuck) or have your Person class inherit from a container:

public class Person : List<Address> { }

Now you can get the behavoir you want, under two conditions:

  1. Do not reference the Person class by its base type (List), and...
  2. Use the 'new' keyword to hide the base List 'add' operation.

The new keyword is necessary, because List.Add(...) is not virtual. This is somewhat wicked to do (possibly bad), but mostly cool in this particular case. In the "new Add(...)" method you write, you include your business logic, and then call the base Add(...) method.

Want to make this even cooler? Make a tree:

public class Node : List<Node> { }

In video games, I've used that trick when writing a game tree.


Well here's one reason why you'd want to do it:

// GrandDad: 
public void CanIWatchTv() {
   return age > 5;
}

// Dad: Grandpa is too liberal
public override void CanIWatchTv() {
   return age > 12;
}

// Son: I don't care what dad says!
public new void CanIWatchTv() {
   return true;
}

In other words, you'd use new when you compltely want to override (not the keyword) what the base method is doing instead of extending it.

In real world scenarios, it should be used sparingly as it goes against the principles of inheritance (should Son be allowed to override his Dad - the answer depends on whether you're a son or dad, but in a perfect world, it shouldn't be).


My understanding is that one of the primary motivations relates to the versioning of libraries over time.

January 1st: Company X releases class Dad as part of Super Library v1.0.

class Dad
{
    virtual public void Foo() { ... };
}

February 1st: You purchase Super Library v1.0 and create subclass Son.

class Son : Dad
{
    public void Bar() { ... };
} 

March 1st: Company X releases Super Library 2.0 adding a new method called Bar. They have no idea you also created a method Bar and their Bar is totally unrelated.

class Dad
{
    virtual public void Foo() { ... };
    virtual public void Bar() { ... };
}

May 1st: You purchase Super Library v2.0 and recompile you Son class against it. To your surprise, you find they added a method called Bar that conflicts with yours. To minimize regression risk, you now mark your Bar method as new to distinguish it from Company X's Bar. Both peacefully co-exist though they strangely have the same name. Their existing code will call their Bar as expected and your existing code will call your Bar as expected.

class Son : Dad
{
    new public void Bar() { ... };
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号