问题描述
例如
BaseClass MyBase()
{
public int Add(BaseClass next)
{
if (this is InheritedA && next is InheritedA)
return 1;
else if (this is InheritedA && next is InheritedB)
return 2;
else if (this is InheritedB && next is InheritedA)
return 3;
else if (this is InheritedB && next is InheritedB)
return 4;
}
}
其中InheritedA
和InheritedB
是它的继承类.其实继承的类更多,Add
根据其操作数的顺序和类型返回不同的结果.
where InheritedA
, and InheritedB
are its inherited classes. In fact, there are more Inherited classes, and the Add
returns different results based on the order and types of its operand.
我正在考虑使用多态性和重载来重写它,但是它变得相当复杂,我必须引入一个辅助方法来解析任一端的类型.
I am thinking of rewriting it using Polymorphism and overloading, however, it becomes rather complicated, I have to introduce an helper method to resolve the type of either end.
例如
InheritedA myA()
{
public override int Add(BaseClass next)
{
return next.AddTo(this);
}
}
现在我必须将 AddTo
放入 BaseClass
,并在继承的类中覆盖它.
Now I have to put AddTo
into BaseClass
, and override it in inherited class as well.
InheritedA myA()
{
public override int AddTo(InheritedA next) { return 1; }
public override int AddTo(InheritedB next) { return 3; }
}
BaseClass myBase()
{
public abstract int Add(BaseClass next);
public abstract int AddTo(InheritedA next);
public abstract int AddTo(InheritedB next);
}
有没有更好的方法?
推荐答案
您正在实现的模式称为双虚拟调度.
The pattern you are implementing is called double virtual dispatch.
单个虚拟调度根据接收者的运行时类型和编译时类型选择调用哪个方法的论点.这是一个传统的虚拟调度:
A single virtual dispatch chooses which method to call on the basis of the run-time type of the receiver and the compile time type of the arguments. This is a traditional virtual dispatch:
abstract class Animal {}
class Tiger : Animal {}
class Giraffe : Animal {}
class B
{
public virtual void M(Tiger x) {}
public virtual void M(Animal x) {}
}
class D : B
{
public override void M(Tiger x) {}
public override void M(Animal x) {}
}
...
B b = whatever;
Animal a = new Tiger();
b.M(a);
调用哪个方法?B.M(Tiger)
和 D.M(Tiger)
没有被选中;我们根据参数的编译时间类型拒绝它们,即Animal.但是我们根据 whatever
是否为 new B() 来选择在运行时调用
BM(Animal)
还是 DM(Animal)
或 new D()
.
Which method is called? B.M(Tiger)
and D.M(Tiger)
are not chosen; we reject them based on the compile time type of the argument, which is Animal. But we choose whether to call B.M(Animal)
or D.M(Animal)
at runtime based on whether whatever
is new B()
or new D()
.
Double virtual dispatch 根据两件事的运行时类型选择调用哪个方法.如果 C# 支持双虚拟分派,但它不支持,则运行时分派将转到 BM(Tiger)
或 DM(Tiger)
,即使编译时类型为参数是动物.
Double virtual dispatch chooses which method to call based on the runtime types of two things. If C# supported double virtual dispatch, which it does not, then the runtime dispatch would go to B.M(Tiger)
or D.M(Tiger)
even though the compile-time type of the argument is Animal.
C# 4 确实支持 dynamic 调度.如果你说
C# 4 does however support dynamic dispatch. If you say
dynamic b = whatever;
dynamic a = new Tiger();
b.M(a);
那么M的分析将完全在运行时使用b
和a
的运行时类型来完成.这速度明显较慢,但确实有效.
Then the analysis of M will be done entirely at runtime using the runtime types of b
and a
. This is significantly slower, but it does work.
或者,如果您想进行双重虚拟调度并在编译时完成尽可能多的分析,那么标准的方法是实现访问者模式,您可以在互联网上轻松查找.
Alternatively, if you want to do double virtual dispatch and get as much analysis done at compile time as possible then the standard way to do that is to implement the Visitor Pattern, which you can look up on the internet easily.
这篇关于如何使用多态性+重载改进这种方法以减少 IS(类型检查)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!