这就是我目前的做法:
ref class Base abstract {};
ref class ConcreteClass1 : public Base {};
ref class ConcreteClass2 : public Base {};
(...and even more...)
void DoStuff(Base ^base)
{
System::Type ^type = base->GetType();
System::String ^name = type->Name;
if(name == "ConcreteClass1")
DoOtherStuff((ConcreteClass1 ^) base);
else if(name == "ConcreteClass2")
DoOtherStuff((ConcreteClass2 ^) base);
(...and even more...)
}
有更“优雅”的方法吗?
根据我的方法,我必须为每个新的Concrete Class添加一个新的else,这让我感觉像是thedailywtf.com上的一个例子。
答案 0 :(得分:2)
嗯,你可以做的一件简单的事情就是compare the types directly而不是使用字符串和类型名称:
void DoStuff(Base ^base)
{
System::Type ^type = base->GetType();
if(type == ConcreteClass1::typeid)
DoOtherStuff((ConcreteClass1 ^) base);
else if(type == ConcreteClass2::typeid)
DoOtherStuff((ConcreteClass2 ^) base);
(...and even more...)
}
但是,它有相当多的“代码味道”。通常,使用抽象类的整个要点是允许多态 - 如果你可以在每种类型上使DoOtherStuff成为虚函数,你可以这样做:
base->DoOtherStuff();
并且会为你调用适当的方法......
答案 1 :(得分:1)
如果你的设计限制了ConcreteClass1
内部ConcreteClass1
特殊内容的所有知识,那就更优雅了。你可以在基类中有一个Process()
函数,它们都是从基类继承的,并且它只是做你想做的任何事情,包括调用DoOtherStuff(this)
?那将有更好的封装,当你添加更多的类时,你不会改变你的调用代码,因为它只是调用base->Process()
并依赖于多态。
答案 2 :(得分:1)
我发现,比if语句更好的设计是使用调度表 - 本质上是从'type'到函数指针/委托的字典。如果子类负责将自己注册到表中,那么您的调度函数就像是:
void DoStuff(Base ^base)
{
System::Type ^type = base->GetType();
m_DispatchTable[type](base);
}
并添加新的调度,它只需要在表中注册自己 - 无需更新代码。这样可以避免维护“if”聚合,如果您需要调用多个函数,可以将调度表映射为更复杂的类型。