如何使用多态性而不是实例?(为什么?

2022-09-03 14:11:49

如果我们采用以下代码:

Shape p1 = new Square();
Square c1;
if(p1 instanceof Square) {
  c1 = (Square) p1;
}

更喜欢多态性而不是实例是什么意思,顺便说一句,为什么它更好?

编辑:我明白什么是多态性;我缺少的是如何使用它而不是.instanceof


答案 1

如果...还。。。(或开关,或访客),和多态性之间的是模块化。有所谓的开放-封闭原则,它基本上意味着,当你向现有程序添加新功能时,你在现有代码中所做的更改越少越好(因为每次更改都需要一些工作,并且可能会引入错误)。因此,让我们比较一下更改的数量:

  • 添加一个新方法(例如,你有 paint() 和 getArea(),让我们添加 getCircumference()):使用 if-else 解决方案,你只需要更改一个文件 - 将包含新方法的文件。使用多态性,您必须更改 Shape 类的所有实现。

  • 添加一种新的形状(你有正方形,圆形 - 让我们添加三角形):使用if-else解决方案,您必须使用if-else查看所有现有类,并为三角形添加一个新的if分支;使用polymporphism,您所要做的就是添加一个新类并在其中实现所有必需的方法。

因此,如果...还。。。或多态性:它取决于模块化。如果您预计以后会添加许多新的子酶,请使用多态性;如果您预计以后会添加许多新方法,请使用以下条件...else...,并且在课堂上只放置最“基本”的方法,如访问器。或者换句话说:当你期望有很多,如果...还。。。分支,你应该宁愿使用多态性,当你期望很少这样的分支时,只要保持如果...还。。。

另外:当您期望很少,如果...还。。。分支,但在很多地方,你应该考虑封装这个,如果...还。。。使用访客模式或只是为每个分支制作一个单独的案例的枚举。


答案 2

这个想法是,你不应该关心你正在处理什么样的形状。例如,如果 Shape 定义了一个抽象的 draw() 方法,那么三角形、正方形和任何其他扩展 Shape 的东西也将具有相同的方法。

多态性的一个简单定义是“将不同的类型视为相同”,即使用相同的接口。

在理想的世界中,我们不想担心我们正在处理的特定类型的对象,只需担心更通用类型的接口,该接口涵盖了其接口中的所有使用场景。

Shape p1 = new Square();
Shape p2 = new Triangle();
p1.draw();
p2.draw();

在此代码中,我们直接在 p1 和 p2 上调用 Shape.draw()。我们不关心实现类的作用,只关心接口(或抽象父类)定义的内容。

编辑:关于问题中的示例,通常建议通过尽可能封装行为来避免这种代码模式。使用 instanceof 可以被视为一种代码异味,因为每当添加新类时,都必须更新所有条件。