# 第 3-3 课课堂练习:Python 与 Java 的继承和多态差异 # # 关键差异已经写进每部分题目,可以直接完成练习。 # 请保留题目、预期结果和自查说明。 # 第一部分:定义 PaymentProcessor 父类 # 1. 定义 __init__(self, channel_name) 方法。 # 2. channel_name 标注为 str,并保存为 self.channel_name。 # 3. 定义 pay(self, amount) 方法,amount 标注为 float。 # 4. pay() 中执行 raise NotImplementedError("子类必须实现 pay() 方法。")。 # # Java 对照提醒: # - 本题暂不使用抽象基类(Abstract Base Class,ABC),先观察普通父类的写法; # - Python 重写方法时不要求 @Override,拼错方法名也不会由该注解提醒。 # 第二部分:定义 CardProcessor 子类 # 1. 使用 class CardProcessor(PaymentProcessor): 表示继承。 # 2. 定义 __init__(self, card_number) 方法,card_number 标注为 str。 # 3. 执行 super().__init__("银行卡"),复用父类初始化逻辑。 # 4. 保存 self.card_number,只保留卡号最后四位即可:card_number[-4:]。 # 5. 重写 pay(self, amount),返回: # “银行卡支付 100.0 元|卡号末四位:1234”。 # # Java 对照提醒: # - Python 3 通常直接写 super(),不需要传当前类和 self; # - super() 按方法解析顺序继续查找方法,不应简单理解为固定的“父类对象”。 # 第三部分:定义 QrCodeProcessor 类,但不要继承 PaymentProcessor # 1. 定义 pay(self, amount) 方法。 # 2. 返回“二维码支付 50.0 元”。 # # 多态重点: # - 该类没有 extends,也没有 implements; # - 只要它提供调用者需要的 pay(),就能参与统一调用; # - 这种“关注行为而非声明类型”的方式称为鸭子类型(Duck Typing)。 # 第四部分:定义 process_payment(processor, amount) 函数 # 1. 调用 processor.pay(amount) 并 return 它的结果。 # 2. processor 的类型注解本题可以省略,不作为验收阻塞项。 # 3. 函数内部不要使用 isinstance() 判断具体类型。 # # Java 对照提醒: # - Java 通常要求 processor 实现统一接口; # - Python 运行时只要求传入对象具有可调用的 pay() 方法。 # 第五部分:定义 main() 并验证两种处理器 # 1. 创建 CardProcessor("6222020012341234")。 # 2. 创建 QrCodeProcessor()。 # 3. 使用 process_payment(card_processor, 100.0) 并输出结果。 # 4. 使用 process_payment(qr_processor, 50.0) 并输出结果。 # 5. 输出 CardProcessor 的方法解析顺序名称: # [class_type.__name__ for class_type in CardProcessor.mro()] # 6. 添加程序入口判断并调用 main()。 # # 预期输出: # 银行卡支付 100.0 元|卡号末四位:1234 # 二维码支付 50.0 元 # ['CardProcessor', 'PaymentProcessor', 'object'] # 完成后自查: # 1. 是否会使用 super() 复用父类初始化; # 2. 是否知道 Python 方法重写不要求 @Override; # 3. 是否能解释 super() 与 MRO 的关系; # 4. 是否知道未继承同一父类的对象也能参与鸭子类型调用; # 5. 是否避免通过 isinstance() 分支实现伪多态; # 6. 是否只把运行错误、结果错误和关键知识点错误视为阻塞项。