【问题标题】:Overloaded functions with inherited parameter具有继承参数的重载函数
【发布时间】:2020-03-04 07:33:42
【问题描述】:
我正在尝试做这样的事情,但我遇到错误:
无法从 AbstractExampleClass 转换为 SpecificExampleClassA。
所以我可能在这段代码中走错了方向,谁能告诉我出了什么问题以及如何修复它。
public abstract class AbstractExampleClass
{
// Code goes here
}
public class SpecificExampleClassA : AbstractExampleClass
{
}
public class SpecificExampleClass : AbstractExampleClass
{
}
public class handler
{
public void Handle(AbstractExampleClass aec)
{
HandleSpecific(aec);
}
public void HandleSpecific(SpecificExampleClassA a)
{
// DoSomething
}
public void HandleSpecific(SpecificExampleClassB b)
{
// DoSomething Else
}
}
【问题讨论】:
标签:
c#
overloading
abstract-class
【解决方案1】:
重载是在编译时解决的,所以你不能指望它根据aec的运行时类型来决定调用哪个重载。 调用的重载必须在编译时决定。
您真正需要的是“subtyping”类型的多态性(也就是 C# 术语中的“多态性”),而不是 ad hoc polymorphism(又名“重载”)。
改为在子类中移动处理程序方法:
public abstract class AbstractExampleClass
{
public abstract void Specific();
}
public class SpecificExampleClassA : AbstractExampleClass
{
public override void Specific()
{
// DoSomething
}
}
public class SpecificExampleClass : AbstractExampleClass
{
public override void Specific()
{
// DoSomething Else
}
}
public class handler
{
public void Handle(AbstractExampleClass aec)
{
aec.Specific();
}
}
【解决方案2】:
这可以由Visitor Pattern处理
public abstract class AbstractExampleClass
{
public abstract void Accept( Handler handler );
}
public class SpecificExampleClassA : AbstractExampleClass
{
public override Accept( Handler handler )
{
handler.HandleSpecific( this );
}
}
public class SpecificExampleClass : AbstractExampleClass
{
public override Accept( Handler handler )
{
handler.HandleSpecific( this );
}
}
public class Handler // the Visitor
{
public void Handle(AbstractExampleClass aec)
{
aec.Accept( this );
}
public void HandleSpecific(SpecificExampleClassA a) // visit method
{
// DoSomething
}
public void HandleSpecific(SpecificExampleClassB b) // visit method
{
// DoSomething Else
}
}
【解决方案3】:
如果你真的必须这样做,你可以这样做:
public void Handle(AbstractExampleClass aec)
{
switch (aec)
{
case SpecificExampleClassA a:
HandleSpecific(a);
break;
case SpecificExampleClassB b:
HandleSpecific(b);
break;
default:
throw new Exception($"What do I do with a '{aec?.GetType()}'?");
}
}
但如果允许您这样做,我推荐一种类似于 Sweeper 回答中的方法。