哪些类不能被子类化?

Posted

技术标签:

【中文标题】哪些类不能被子类化?【英文标题】:Which classes cannot be subclassed? 【发布时间】:2012-04-21 03:35:43 【问题描述】:

对于哪些内置和标准库类不可子类化(“final”)有什么规定吗?

从 Python 3.3 开始,以下是一些示例:

bool function operator.itemgetter slice

我找到了一个question,它处理“最终”类的实现,包括 C 和纯 Python。

我想了解什么原因可以解释为什么首先选择一个类作为“最终”类。

【问题讨论】:

NoneType 是另一个例子。 一个 Python 实现中的最终类可以在另一个实现中子类化吗?我希望有人可以确认它永远不会发生。否则,为一个实现编写的代码在移植到另一个实现时可能会中断(同样非常痛苦:想象一下,如果有人继承了function,现在需要重构代码以避免这种继承)。 请注意,PyPy 也拒绝对您的四个示例进行子类化......即使它没有 CPython 限制。他们的代码库中可能记录了一个原因。 NotImplementedType(即type(NotImplemented))和ellipsis(即type(...))是另外两个例子。与None 一样,没有理由拥有多个这些类的实例,如果允许,检查它们会更尴尬(if x is None 必须变为if isinstance(x, type(None)))。我想,原则上,您可以通过查看类型定义中tp_flags 值的来源来获得完整列表。 @agf:请参阅this post,了解为什么要继承itemgetter;和this post 解释为什么你可能想要子类function(这个是旧的,所以其中一些参数可能不适用)。 【参考方案1】:

一个类在 Python 中成为“final”似乎有两个原因。

1.违反类不变量

遵循单例模式的类具有一个不变量,即实例数量有限(预先确定)。在子类中任何违反此不变量的行为都将与该类的意图不一致,并且无法正常工作。例子:

boolTrueFalse;见Guido's comments NoneType: None NotImplementedType: NotImplemented ellipsis: Ellipsis

在这个类别中可能有除单例模式以外的情况,但我不知道。

2.没有说服力的用例

在 C 中实现的类需要额外的工作以允许子类化(至少在 CPython 中)。在没有令人信服的用例的情况下做这样的工作并不是很有吸引力,因此志愿者不太可能挺身而出。例子:

function;见Tim Peters' post

注1:

我最初认为有有效的用例,但对functionoperator.itemgetter 的子类化兴趣不足。感谢@agf 指出here 和here 提供的用例并不令人信服(请参阅@agf cmets 的问题)。

注2:

我担心另一个 Python 实现可能会意外地允许子类化 CPython 中的 final 类。这可能会导致代码不可移植(一个用例可能很弱,但如果他们的 Python 支持,有人可能仍会编写子类function 的代码)。这可以通过在 Python 文档中标记所有不能被子类化的内置和标准库类来解决,并要求所有实现在这方面都遵循 CPython 行为。

注3:

CPython 在上述所有情况下产生的消息是:

TypeError: type 'bool' is not an acceptable base type

正如许多关于这个主题的问题所显示的那样,它非常神秘。我将提交一个建议,在文档中添加一个段落来解释最终类,甚至可能将错误消息更改为:

TypeError: type 'bool' is final (non-extensible)

【讨论】:

当然,如果您正在编写薛定谔猫的模拟,您可能希望将bool 子类化为包含unknown :-P 只是在开玩笑 @Endophage:Qbit 肯定是一种有用的类型,但它不是bool 的子类,事实上,恰恰相反,每个布尔值都是一种 qbit!一个恰好被观察到的。不过,我可能会和__subclasscheck__ 和朋友一起处理这个案子。 @TokenMacGuy 出色的观察!那么为什么我们不在 Python 中有一个 Qbit 类,它是 bool 的子类!我要求它应该是这样! :-P 但在观察/测试时,Qbit 的值将始终为 False 或 True。似乎你只需要一个 bool 的子类,它只在观察时进行“计算”......(LazyBool @SingleNegationElimination @Endophage 也许这就是为什么bool 不能是Enum 基类的原因,Guido 不玩骰子?

以上是关于哪些类不能被子类化?的主要内容,如果未能解决你的问题,请参考以下文章

Java面试题|普通类和抽象类有哪些区别?

抽象类抽象方法

c#中接口可不可以被实例化?

抽象类特点

抽象方法真的不能实例化么?

抽象类abstract(包含抽象方法的类)