OBJECT DESIGN WORKSHOP
该继承,还是该组合?
看到两个类有共同代码,不等于马上就该写继承。先问关系是不是稳定的“是一种”,再看替换父类后是否仍然说得通。确实需要继承时,super() 也不是简单地“找爸爸”,它会沿当前类的 MRO 去找下一站。
研究生与学生
“研究生是一种学生”长期成立,而且研究生应该能用在任何期待学生对象的位置。怎样表达更自然?
先别急着看答案
把左边对象替换成右边类型试着读一句话,再考虑它们是“是一种”还是“拥有/使用一个”。
子类放进需要父类的代码中,原有承诺还成立吗?
今天的“是一种”,会不会很快变成可更换的能力或零件?
继承会把子类绑在父类接口上;组合通常更容易替换和测试。
super() 的下一站是谁?
下面的菱形结构中,RescueRobot(Flyer, Swimmer) 调用 move()。按步骤追踪,每个类只经过一次。
RescueRobot调用 move()Flyer记录“展开机翼”Swimmer记录“启动推进器”Machine记录“开始移动”协作式调用记录
当前定义:class RescueRobot(Flyer, Swimmer)
准备开始先从
RescueRobot 查找 move。每个实现都调用 super().move(),调用链才会继续沿 MRO 前进。继承表达“是什么”
当子类确实是一种父类,并愿意承担父类接口的承诺,继承能让共同行为自然复用。
组合表达“有什么”
把会替换、会变化的能力做成独立对象,由主对象持有它,通常更灵活。
MRO 决定“下一站”
在多重继承里,super() 沿 MRO 前进。协作链上的方法应保持兼容签名并继续调用 super()。