python - 为什么用多态性替换条件有用?
问题描述
正如refactoring.guru上所示,我想澄清一件事一直困扰着我“用多态性替换条件” 。我在下面的 python 中重新创建了示例:
IF 语句代码
def get_speed(bird):
base_speed = 10
if bird == "AfricanBird":
return base_speed * 2 - 10
elif bird=="EuropeanBird":
return base_speed * 1.85 - 12
elif bird=="NorwegianBlue":
return base_speed * 2.5 - 11
else:
raise ValueError("Bird type invalid")
if __name__=="__main__":
b = "EuropeanBird"
speed = get_speed(b)
print(speed)
用多态替换 IF 语句
from abc import abstractmethod, ABC
class Bird(ABC):
def get_base_speed(self):
return 10
@abstractmethod
def get_speed(self):
pass
class AfricanBird(Bird):
def get_speed(self):
return self.get_base_speed()*2-10
class EuropeanBird(Bird):
def get_speed(self):
return self.get_base_speed()*1.85-12
class NorwegianBlue(Bird):
def get_speed(self):
return self.get_base_speed()*2.5-11
if __name__=="__main__":
# This *still* has to be specified by the user somewhere.
# For example in a GUI or input text file.
b = "EuropeanBird"
# Here is the if statement again!!
if b == "AfricanBird":
b = AfricanBird()
elif b=="EuropeanBird":
b = EuropeanBird()
elif b=="NorwegianBlue":
b = NorwegianBlue()
else:
raise ValueError("Bird type invalid")
print(b.get_speed())
通过允许您从基类继承并重新定义行为而不是在if
语句中添加新分支,我得到了多态性增加通用性的部分。然而,在一天结束的时候,您仍然需要在您的主代码中的某处决定使用您的基类的哪个实现(我的第二个示例中的第 26 行),这会强制该if
语句重新出现。
我错过了重点吗?有没有办法完全消除客户端代码中的条件语句?
解决方案
在您的示例中,您将一个纯字符串转换为完整的类层次结构。由于所有需要的都是处理字符串,并且输入是该字符串,因此多态性除了学习之外什么都不增加。
当内部创建各种对象时,以及当这些对象具有某些具有特定性的共同行为时,情况就会有所不同。事实上,选择应该在构思时出现,在编写任何代码行之前。您分析要处理的对象以及它们必须实现的行为。那时,应该出现可能的类层次结构。
实际上,只有在您跳过开发中的建模阶段并且发现自己在整个代码中不断重复相同的条件时,才应该使用多态性替换一堆条件。几十年来我一直在使用 Python、Java 和 C++,并且从未用多态性代替条件:要么模型在概念时表现出层次结构,并且必须首先实现,要么没有底层对象,多态性只会添加一个无用的复杂性。
TL/DR:如果你发现自己用多态性代替了条件,那只是意味着你在编写代码之前没有首先考虑你想要开发什么以及你应该如何开发它。
推荐阅读
- javascript - Vue JS 2:在 beforeCreate 之后停止生命周期
- java - 将 Intellij 键盘设置映射到 Visual Studio
- karate - 如何根据条件将值为 Null 的新键添加到动态响应体中
- python - 没有找到 PyJWT<3.0.0,>=2.0.1 的匹配分布
- javascript - 在 useEffect 调用后,React Hooks 改变了 asycn 函数内部数组的状态
- python - 如何在 numba 中使用 numpy 函数
- python - ValueError:您必须指定一个句点或 x 必须是具有 DatetimeIndex 且频率未设置为 None 的 pandas 对象 - decompose() 时间序列
- python - 获取当前 nox 会话的名称
- groovy - Nexus 3 使用 Groovy 脚本创建清理策略
- c++ - 尝试在渲染线程上执行 opengl 调用时,如何摆脱抛出的异常?