问题
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.
- I don't believe that. Such a powerful language and yet, there's no way of telling the compiler which method is which.
- 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