C# 强制方法从基调用子类new方法
我的理解是,子类的行为与父类完全相同,除了附加的方法或那些使用C# 强制方法从基调用子类new方法,c#,class,methods,public,protected,C#,Class,Methods,Public,Protected,我的理解是,子类的行为与父类完全相同,除了附加的方法或那些使用new和override关键字“重写”的方法。显然,这是不对的 请参阅下面的代码(为便于阅读,删除括号) 我已经知道,我可以用new关键字将BIG.Output(string)隐藏为小写。直接打电话时,效果非常好 >> foo.Output("Outputting...") SMALL - Outputting... 这与我的理解有冲突。我认为定义类SMALL:BIG与定义类SMALL并从BIG复制粘贴所有方法完全一样。
new
和override
关键字“重写”的方法。显然,这是不对的
请参阅下面的代码(为便于阅读,删除括号)
我已经知道,我可以用new
关键字将BIG.Output(string)
隐藏为小写。直接打电话时,效果非常好
>> foo.Output("Outputting...")
SMALL - Outputting...
这与我的理解有冲突。我认为定义类SMALL:BIG
与定义类SMALL
并从BIG复制粘贴所有方法完全一样。简言之,我认为上面的小班相当于:
class SMALL
public void Output(string text = "")
Console.WriteLine("SMALL - " + text);
public void CallingOutput()
Output("Outputting...");
显然这是不正确的,因为
>> foo.CallingOutput()
BIG - Outputting...
当间接调用时,它仍然使用来自BIG
的原始输出(字符串)
正确的方法是什么,以便foo.CallingOutput()
输出
“小-输出…”
假设我没有访问BIG
的权限,并且不允许进行任何更改。我不想隐藏CallingOutput()
,因为这基本上是重写类。
(是的,隐藏CallingOutput()
可以让它工作)
在发布这篇文章之前,我做了一些搜索,在C++
中发现了一个类似的问题。然而,答案是不可能的
将关键字
new
替换为override
,如下所示:
class SMALL:BIG
public override void Output(string text = "")
Console.WriteLine("SMALL - " + text);
创建一个垫片
不能修改或重写现有类中的任何内容,除非它被设计为被重写。这是故意的
也就是说,您可以创建一个新的“shim”(pass-through)类,该类与原始类完全相同,但其成员被声明为virtual。这是通过使用new
和virtual
修饰符来实现的
拥有shim类后,可以根据法线重写该方法。例如:
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...");
}
}
现在您有了一个Shim类,它将允许您想要的内容。因此,将其分为子类(而不是大类)并查看会发生什么:
class Small : Shim
{
public override void Output(string text) { Console.WriteLine("Small - {0}", text); }
}
测试它:
Shim s = new Shim();
s.CallingOutput(); //Original behavior
Shim s = new Small();
s.CallingOutput(); //Overridden behavior
输出:
Big - Outputting...
Small - Outputting...
在基类中声明方法
virtual
,在child中声明方法override
,然后基类将对其进行装箱,new
按设计不起作用是的,override
和new
是不可互换的。它们有不同的效果。通过显示您对foo
的使用,您的问题可以变得更清楚;foo
的类型和对象创建。@abatishchev如上所述,我不允许对BIG进行更改。然后不要继承它。它不是为继承而设计的。相反,你可以使用构图。创建一个小类来引用一个大对象,并根据需要使用它。不会在所有情况下都有效,但可能会让你达到你需要的目的?那么这是通过设计:你尝试攻击大(通过覆盖非虚拟的内容来改变其行为),而框架不允许你这样做(新的只在同一类型的范围内工作),因为这不是设计和预期的大,抱歉。但是,请看@itsme86的答案-这是正确的方法(但并不总是适用)我不能对BIG
和BIG进行更改。Output()
未标记为虚拟、抽象或重写,因此我不能这样做。在基类中执行此操作您所说的基类是什么意思?大不是基本阶级吗?是的!读了这篇文章你就会明白我不明白。我在问题和评论中说了两次,我不允许对基类进行更改。它是原样的,并且没有标记为虚拟、抽象或覆盖,因此我不能使用override
关键字。不,这不是我想要的。目标是让CallingOutput
在SMALL
中调用输出。在我的问题中,我已经实现了您在示例中所做的,甚至没有使用Shim
类。请再检查一遍!正如我所说,你不能拥有你想要的东西,这是故意的。在我的示例中,可以使用垫片
而不是大垫片。这与您已经做的不同,因为Small中的覆盖实际上是有效的。我将更新示例代码。正如我在问题中所述,我不想“重写”CallingOutput
,因为这基本上是重写BIG
。是的,你是对的,它不应该被覆盖,如果它最初不是被设计成这样的,我理解。对不起,你不能得到你想要的。我建议使用shim比重写BIG要省力,因为您仍然可以访问this
,仍然可以访问受保护的成员,仍然可以将实例存储在IEnumerable
中,或者将其作为参数传递给需要使用BIG
的地方,等等。尽管如此,您还是可以调用它。
Big - Outputting...
Small - Outputting...