也许我的信息过时了,但我打算帮助某人学习 OOP 语言、概念等。我想使用一些动态的东西。我的想法是 Python,但后来我读到它没有接口。接口不是学习 OOP 概念需要知道的东西吗?
1 回答
我的想法是 Python,但后来我读到它没有接口。
好吧,您可以在 Python 中使用接口。标准库有模块,也有PyProtocolsabc
等第三方模块(Zope 和 Twisted 等框架也有自己类似的想法)。
关键是它们不是必需的,甚至经常是不必要的。您“想使用动态的东西”吗?这就是动态的含义:函数采用具有正确接口的任何对象,而不需要在任何地方静态定义该接口,更不需要对象静态声明它支持该接口。
所以,当你问:
接口不是学习 OOP 概念需要知道的东西吗?
答案是不”。接口是学习Java 风格的 OOP需要知道的东西,但通常不是学习 OOP 需要知道的东西。
从不同的角度考虑这一点:在 Python 中执行 Javascript 样式的 OOP 是可能的,但并不容易;就像在 Java 中一样,类对于 Python 来说太基础了,没有它就无法生存。这是否使 Python 和 Java 成为糟糕的 OO 语言而 Javascript 成为一种好的语言?不; 它只是使它们成为不同的面向对象语言。
蒙克特想知道“wtf 是一个接口???”
接口(又名协议、抽象基类、抽象类型……)只是一种可用于静态和/或动态类型检查和/或以与类完全相同的方式进行切换的类型。
那么,这样做有什么好处呢?好吧,理论上,你永远不需要检查类型——这不仅是 Python 之禅的一部分,也是核心 OO 教条的一部分——但实际上有时你会这样做。因此,能够命名您的抽象类型,并声明一个类支持各种不同的抽象类型,会很有用。
当然,您可以使用普通的旧类来做到这一点,但是能够显式声明一个类型是抽象的也有助于提高可读性和调试。PEP 3119以 Python 为中心的方式解释了基本原理。
但是在像 Java 这样的语言中,还有两个额外的好处。
首先,如果你有静态类型检查,你就不能编写一个可以接受例如列表、元组、集合、frozenset 或迭代器的函数。但是你可以写一个接受Iterable的函数,然后声明list、tuple等都提供了Iterable接口,然后就万事大吉了。(在具有动态类型检查的语言中,duck typing 已经为您解决了这个问题——您的代码适用于任何对象,该对象的__iter__
方法返回的行为符合您的预期。)
其次,如果你有静态数据成员布局和/或 vtable 样式的方法覆盖机制,多重继承是非常棘手的。但是多重继承也非常有用。所以在Java中,接口就像一个类,但没有数据成员或方法实现,你可以从任意多个接口继承,但只能继承一个类。这给 Java 带来了多重继承的一些好处,而没有任何问题。(在具有动态数据成员和动态方法查找的语言中,只要你有一个明智的 MRO 算法,就像 Python 那样,你就可以获得多重继承的所有好处,而不会出现任何问题。)