79 lines
2.5 KiB
Python
79 lines
2.5 KiB
Python
# 第 3-3 课完整示例:Python 与 Java 的继承和多态差异
|
||
#
|
||
# 示例集中演示 super()、方法重写、多继承的方法解析顺序和鸭子类型。
|
||
|
||
|
||
class Notifier:
|
||
"""所有通知器都可以复用的基础类。"""
|
||
|
||
def __init__(self, sender: str) -> None:
|
||
self.sender = sender
|
||
|
||
def send(self, message: str) -> None:
|
||
"""定义统一操作;具体子类负责实现发送行为。"""
|
||
raise NotImplementedError("子类必须实现 send() 方法。")
|
||
|
||
|
||
class EmailNotifier(Notifier):
|
||
"""通过继承实现邮件通知器。"""
|
||
|
||
def __init__(self, sender: str, address: str) -> None:
|
||
# Python 3 中通常直接写 super(),不需要传入类名和 self。
|
||
super().__init__(sender)
|
||
self.address = address
|
||
|
||
def send(self, message: str) -> None:
|
||
"""重写父类方法;Python 不要求添加 @Override。"""
|
||
print(f"邮件|{self.sender} -> {self.address}:{message}")
|
||
|
||
|
||
class ConsoleNotifier:
|
||
"""没有继承 Notifier,但同样提供 send() 方法。"""
|
||
|
||
def send(self, message: str) -> None:
|
||
print(f"控制台|{message}")
|
||
|
||
|
||
class LogMixin:
|
||
"""混入类(Mixin)只提供一项可复用能力。"""
|
||
|
||
def record(self) -> None:
|
||
print("通知行为已记录。")
|
||
|
||
|
||
class LoggedEmailNotifier(EmailNotifier, LogMixin):
|
||
"""Python 可以继承多个类,查找方法时遵循 MRO。"""
|
||
|
||
|
||
def send_message(notifier, message: str) -> None:
|
||
"""只要传入对象具有 send() 方法,就可以完成调用。"""
|
||
notifier.send(message)
|
||
|
||
|
||
def main() -> None:
|
||
"""运行继承和多态差异示例。"""
|
||
email = EmailNotifier("系统", "user@example.com")
|
||
console = ConsoleNotifier()
|
||
|
||
print("差异 1:子类使用 super() 复用父类逻辑,不需要写父类名称。")
|
||
print(f"邮件发送者:{email.sender}")
|
||
print()
|
||
|
||
print("差异 2:Python 重写方法时没有强制的 @Override。")
|
||
email.send("课程开始")
|
||
print()
|
||
|
||
print("差异 3:鸭子类型关注对象有什么行为,而不是声明了什么接口。")
|
||
send_message(email, "继承得到 send()")
|
||
send_message(console, "未继承也能调用 send()")
|
||
print()
|
||
|
||
print("差异 4:Python 支持多继承,并通过 MRO 决定方法查找顺序。")
|
||
logged_email = LoggedEmailNotifier("系统", "admin@example.com")
|
||
logged_email.record()
|
||
print([class_type.__name__ for class_type in LoggedEmailNotifier.mro()])
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|