在无法修改的类中实现多态行为的最佳方法是什么?我目前有一些代码:
if(obj is ClassA) {
// ...
} else if(obj is ClassB) {
// ...
} else if ...
显而易见的答案是向基类添加一个虚方法,但不幸的是代码在不同的程序集中,我无法修改它。有没有比上面的丑陋和慢速代码更好的方法来处理这个问题?
答案 0 :(得分:9)
嗯...似乎更适合Adapter。
public interface ITheInterfaceYouNeed
{
void DoWhatYouWant();
}
public class MyA : ITheInterfaceYouNeed
{
protected ClassA _actualA;
public MyA( ClassA actualA )
{
_actualA = actualA;
}
public void DoWhatYouWant()
{
_actualA.DoWhatADoes();
}
}
public class MyB : ITheInterfaceYouNeed
{
protected ClassB _actualB;
public MyB( ClassB actualB )
{
_actualB = actualB;
}
public void DoWhatYouWant()
{
_actualB.DoWhatBDoes();
}
}
看起来像很多代码,但它会使客户端代码更接近你想要的。此外,它还会让您有机会思考您实际使用的界面。
答案 1 :(得分:5)
查看Visitor模式。这使您可以在不更改类的情况下将虚拟方法添加到类中。如果您正在使用的基类没有Visit方法,则需要使用带有动态强制转换的扩展方法。这是一些示例代码:
public class Main
{
public static void Example()
{
Base a = new GirlChild();
var v = new Visitor();
a.Visit(v);
}
}
static class Ext
{
public static void Visit(this object b, Visitor v)
{
((dynamic)v).Visit((dynamic)b);
}
}
public class Visitor
{
public void Visit(Base b)
{
throw new NotImplementedException();
}
public void Visit(BoyChild b)
{
Console.WriteLine("It's a boy!");
}
public void Visit(GirlChild g)
{
Console.WriteLine("It's a girl!");
}
}
//Below this line are the classes you don't have to change.
public class Base
{
}
public class BoyChild : Base
{
}
public class GirlChild : Base
{
}
答案 2 :(得分:0)
我想说这里的标准方法是将你想要“继承”的类包装为受保护的实例变量,然后模拟包装类的所有非私有成员(方法/属性/事件/等)。在你的容器类中。然后,您可以将此类及其适当的成员标记为虚拟,以便您可以使用标准多态性功能。
这是我的意思的一个例子。 ClosedClass
是程序集中包含的类,您的代码无权访问。
public virtual class WrapperClass : IClosedClassInterface1, IClosedClassInterface2
{
protected ClosedClass object;
public ClosedClass()
{
object = new ClosedClass();
}
public void Method1()
{
object.Method1();
}
public void Method2()
{
object.Method2();
}
}
如果您引用的任何程序集都设计得很好,那么您可能想要访问的所有类型/成员都将被适当地标记(抽象,虚拟,密封),但实际上并非如此(有时您可以甚至在基类库中遇到过这个问题。在我看来,包装类是走到这里的方式。它确实有它的好处(即使你想要派生的类是可继承的),即删除/更改你不希望你的类的用户有权访问的方法的修饰符。 BCL中的ReadOnlyCollection<T>
就是一个非常好的例子。
答案 3 :(得分:0)
看一下Decorator模式。 Noldorin实际上解释了它而没有给出模式的名称。
Decorator是在不继承的情况下扩展行为的方式。我在Noldorin代码中唯一要改变的是构造函数应该接收你正在装饰的对象的实例。
答案 4 :(得分:-1)
Extension methods提供了一种向现有类添加其他方法签名的简便方法。这需要3.5框架。
创建一个静态实用程序类并添加如下内容:
public static void DoSomething(this ClassA obj, int param1, string param2)
{
//do something
}
在页面上添加对实用程序类的引用,此方法将显示为ClassA的成员。您可以通过这种方式重载现有方法或创建新方法。