我们有一些文档类型:
class Document
{
public void virtual Print()
}
class PDF : Document
{
public void override Print()
{
Console.WriteLine("PDF Printed");
}
}
class Excel : Document
{
public void override Print()
{
Console.WriteLine("Excel Printed");
}
}
假设我们有一个文档列表(Document对象),我们在所有文档上调用虚函数Print()。
foreach(Document doc in DocumentsList)
{
doc.Print();
}
我知道多态性是实现它的非常复杂的方法,但是 我们是否可以使用switch语句以及 来实现相同的功能?我与一位同事就此进行了长时间的争论,他说这是可能的。是吗?
答案 0 :(得分:5)
是的,你可以,当然你可以在每次迭代时询问列表成员,并且有很多技术可以实现这一点(例如属性,内部类型字段等)。
事实上你在C#中所做的一切都可以在汇编程序中完成! 但是,我几乎看不到避免OOP优势的任何好处。
答案 1 :(得分:4)
这是一个有趣的问题,因为使用开关的例子通常用来演示你通常不想这样做。
您可以使用这样的文档类,而不是使用继承:
class Doc {
public:
enum DocType{PDF,EXCEL}
private:
DocType docType;
}
然后你只需使用
switch (doc.getDocType()){
...etc...
}
然而,有几个原因通常使用继承更好。想象一下,例如,您想要添加其他文档类型。然后你不仅需要添加另一个枚举字段,而且(这就是大问题)你还必须更改使用Document类的所有代码中的每个switch语句。这很烦人,通常你不想这样做。
答案 2 :(得分:4)
是的,您可以随时使用开关(或if-else链),询问类型。您可以将文档类型信息保存在对象中,例如作为枚举,并在交换机中使用它。
为什么你不应该这样做?因为在添加新的派生类型时必须扩展所有这些开关。
为了避免这种情况,你可以实现更自动的东西:有一个指向函数(或C#中的委托)的指针列表,你用适合这个特定对象的函数为每个单个对象填充(例如{{1对于PDF文件,委托将指向print
,对于Excel文件指向print_pdf()
。嘿,你手工制作了一个穷人的多态性。
关于多态的好处是使用多态对象的代码可以是类型不可知的。它不知道对象实际具有什么样的精确类型,并且不想知道。在编写处理对象的代码时,可能不存在精确类型。所有详细信息都隐藏在类型中,这对维护来说非常棒。
答案 3 :(得分:0)
多态性是实现这一目标的方法。如果您选择switch
语句,则需要使用Reflection
或is
关键字来确定要调用的对象Print()
。