SDE / Applied Scientist · Coding / Fundamentals

Amazon Intern:Inheritance 与 Polymorphism,重写方法到底证明什么?

区分代码复用与动态派发,围绕父类合同、替换原则和组合边界组织例子。

题目重点:区分代码复用与动态派发,围绕父类合同、替换原则和组合边界组织例子。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 题目问inheritance vs polymorphism,并让写inheritance例子override父方法;语言未给,本文用Python语义的教学对象描述。
  • 不假定原题是C++ virtual dispatch或Java overloading;重载、重写和动态派发必须按指定语言分别回答。
  • 本文无嵌入代码,描述对象调用及预期结果;真实书写练习应在所选语言中运行同一合同测试。

解题路线

  1. 继承定义类型/实现关系,子类复用或扩展父类;多态让统一操作对不同实际对象产生相应行为。可以有继承但没有所需动态行为,也可用协议/duck typing实现多态而不继承同一父类。
  2. 教学父类Notifier提供send(message)并约定返回投递结果,EmailNotifier/ChatNotifier分别重写send。调用者只依send合同,对不同实例逐一调用同名操作。这才展示运行时行为选择,单独创建一个子类而未调用统一接口只展示继承结构。
  3. override保留可替代合同:合法输入范围不应更窄,承诺输出/错误语义不能变弱。父类允许空消息而子类突然抛错,或父类承诺返回result子类只返回None,都可能破坏调用者。类型兼容不等于行为可替代。
  4. overload通常是同名不同参数签名的选择,override是派生实现替换父类方法;Python里反复定义同名方法不会自动获得Java式重载集合。语言不同,静态/动态分派规则和访问控制也不同。
  5. 如需复用日志/重试,组合RetryingNotifier持有实现对象可能更清晰;继承RetryingEmailNotifier再乘各种渠道会形成组合爆炸。组合并非总优于继承,关键是关系稳定性、可替换合同与扩展方向。
  6. 确认方法解析顺序、super调用与构造过程。父类初始化调用可重写方法可能在子类状态未就绪时执行,别只看输出正确的快乐路径。Python数据模型参考:https://docs.python.org/3/reference/datamodel.html。

手动走一遍

训练输入同一消息给EmailNotifier与ChatNotifier,调用者取得各自投递结果,且共享结果结构。再增加第三种渠道时调用者无需按type写if分支;所有实现跑同一套“合法消息/失败语义”验收。反例是子类重写send却改成要两个参数,父类接口调用即失败。

规模与取舍

概念题无需虚构固定大O:成本取决send具体实现。动态派发的常量开销与发送网络成本分开,真正规模风险可能是类层次和测试组合增长。

易错点与追问

容易失分的边界

  • 继承与多态同义。
  • 把方法重写当重载。
  • 子类缩窄输入破坏父类合同。
  • 只有子类实例未展示统一接口调用。
  • 为了共享两行代码强建继承树。

继续深挖

  • duck typing怎样支持无继承多态?
  • super是否总等于调用直接父类?
  • 协议与抽象基类怎样选择?
  • 如何用合同测试核可替换性?

技术参考

  • Python 数据模型:公开方法/语言合同参考,本文示例参数自拟,不代表题目数据或实际项目实现。
✓已复制微信号!