Force method from base to call a subclass new method

∥☆過路亽.° 提交于 2021-02-11 12:14:30

问题


My understanding is that a subclass behaves exactly like the parent class except for the additional methods or those that get "rewritten" with the new and override keywords. Apparently, that's not correct.

Please see the code below (brackets removed for readability)

class BIG
    protected void Output(string text = "")
        Console.WriteLine("BIG - " + text);

    public void CallingOutput()
        Output("Outputting...");

class SMALL:BIG
    public new void Output(string text = "")
        Console.WriteLine("SMALL - " + text);

class Program
    static void Main(string[] args)
        SMALL foo = new SMALL();

I already know that I can hide the BIG.Output(string) in SMALL with the new keyword. When calling directly, it works perfectly.

>> foo.Output("Outputting...")
SMALL - Outputting...

Here is where it conflicts with my understanding. I thought defining class SMALL:BIG was exactly the same as if I define class SMALL and copy-paste all method from BIG. In short, I thought the SMALL class above was equivalent to this:

class SMALL
    public void Output(string text = "")
        Console.WriteLine("SMALL - " + text);

    public void CallingOutput()
        Output("Outputting...");

Apparently that is not correct because

>> foo.CallingOutput()
BIG - Outputting...

It is still using the original Output(string) from BIG when called indirectly.

What is the right way of doing it so that foo.CallingOutput() would output

"SMALL - Outputting..."

Assuming that I don't have access to BIG and not allowed to make any changes. And I don't want to have to hide CallingOutput() also because that is basically rewriting the class. (Yes, hiding CallingOutput() makes it work)

I did some searching before posting this and found a similar question in C++. However, the answer for that is not possible.

  1. I don't believe that. Such a powerful language and yet, there's no way of telling the compiler which method is which.
  2. It's a different language so this post is allowed as it can't be considered a duplication.

回答1:


replace keywords new by override as this :

class SMALL:BIG
public override void Output(string text = "")
    Console.WriteLine("SMALL - " + text);



回答2:


Create a shim

You can't modify or override anything in the existing class unless it was designed to be overridden. This is by design.

That being said, you can create a new "shim" (pass-through) class that is exactly like the original class but with the member being declared as virtual. This is accomplished by using both new and virtual modifiers.

Once you have the shim class, you can override the method per normal. Example:

class Big
{
    public void Output(string text) { Console.WriteLine("Big - {0}", text); }

    public void CallingOutput()
    {
        Output("Outputting...");
    }
}

class Shim : Big
{
    public new virtual void Output(string text) { base.Output(text); }

    public void CallingOutput()
    {
        Output("Outputting...");
    }
}

Now you have a Shim class that will allow what you want. So subclass it (instead of Big) and see what happens:

class Small : Shim
{
    public override void Output(string text) { Console.WriteLine("Small - {0}", text); }
}

Test it:

Shim s = new Shim();
s.CallingOutput();   //Original behavior

Shim s = new Small();
s.CallingOutput();   //Overridden behavior

Output:

Big - Outputting...
Small - Outputting...

Example on DotNetFiddle



来源:https://stackoverflow.com/questions/50184162/force-method-from-base-to-call-a-subclass-new-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!