一个类可以直接继承多少个类
C++说:想继承几个都行,个类只要你别搞出菱形继承的可直烂摊子。Java说:一个,接继就一个,承多多一个都不行。个类Python在中间和稀泥:语法上随便写,可直但你要是接继真继承了七八个类,那MRO(方法解析顺序)算起来能让你怀疑人生。承多 直接说结论:单继承语言里,个类类只能继承一个父类;多继承语言里,可直理论上没上限,接继但实际工程里超过三个就基本是承多灾难了。这不是个类语法限制,是可直大脑限制——人脑能同时追踪的继承关系就那么几条,多了必然乱套。接继 我见过最离谱的代码,是个老项目里的一个类,直接继承了六个类。当时改需求,要往那个类里加个方法。我顺着继承链往上翻,发现这个方法名在六个父类里出现了四种不同的实现,有的带装饰器,有的走元类,还有的直接操作了底层C接口。最后我花了整整两天才搞清楚调用顺序,期间一度怀疑自己是不是不适合写代码。 那种感觉就像你拿到一盒混在一起的乐高零件,说明书上写着“拼成任意形状即可”,但等你拼到一半才发现,每个零件都来自不同的套装,接口对不上,颜色还互相冲突。 Java社区的人经常嘲笑C++的多继承,说那是“魔鬼的礼物”。但C++程序员会反呛:你那个接口多继承算什么本事,有本事来试试真正的钻石继承——A是基类,B和C都继承A,然后D同时继承B和C。这时候D里到底有几份A的数据?两份?还是一份?C++用虚继承解决了,但虚继承的初始化规则复杂到连很多老手都记不全。 Python的做法挺有意思。它允许你写class Foo(Bar, Baz, Qux),但解析方法时用的是C3线性化算法。这个算法会保证每个父类只被处理一次,还保持了子类优先的顺序。听起来很完美对吧?但你要是把继承列表写得稍微复杂点,比如某个父类又继承了另一个父类的兄弟类,解释器直接给你抛个TypeError,说“无法创建一致的MRO”。这时候你就得像个解绳子的匠人一样,慢慢调整类的声明顺序,直到所有依赖关系能排成一条直线。 我个人觉得,继承数量这事,本质上是个信息管理问题。一个类继承的父类越多,它需要对外承诺的接口就越多,内部状态就越复杂。哪怕每个父类都写得干干净净,组合起来的复杂度是指数级上升的。你想想,一个类相当于一个员工,一个父类相当于一个部门经理。员工只向一个经理汇报,事情清楚明了;向两个经理汇报,就得协调优先级;向六个经理汇报?那员工不用干活了,整天开会就行。 有个经验法则我是信的:如果你发现自己写的类需要继承超过两个父类,大概率是你抽象错了。更可能的情况是,你应该用组合——把那些“父类”变成这个类的成员变量,而不是它的血缘关系。组合是“有一个”的关系,继承是“是一个”的关系。你想想,一个“会飞的鱼”到底是鱼的一种,还是鱼和鸟的组合体?现实世界没有标准答案,但代码世界里有——能组合就别继承,能单继承就别多继承。 当然,也有例外。比如混入类(Mixin)这种用法,就是故意让一个类继承一堆没有状态的工具类,每个工具类只提供几个方法,不存数据。这种情况下,哪怕继承十个八个,也不会出大问题,因为状态只有一份,方法只是被“混”进来了。但你要是把有状态的类也这么搞,那等于自己给自己挖坑。 所以回到标题那个问题:一个类能直接继承多少个类?答案是——语法上取决于语言,工程上取决于你的脑子。你要是脑子够清楚,继承三个也能写得明明白白;你要是脑子一团浆糊,单继承一个类都能把逻辑绕晕。代码这东西,从来不是看你能用多少特性,而是看你能在不用某个特性的时候,把问题解决得多漂亮。
- 最近发表
- 随机阅读
- 搜索
-
- 友情链接
-