我有许多类,它们都共享相同的方法,只是实现方式不同。在Java中,让这些类中的每一个实现一个接口或扩展一个抽象类都是有意义的。Python是否有与此类似的东西,还是我应该采用其他方法?
Python接口背后有一个故事。多年来一直保持主导地位的原始态度是您不需要它们:Python在EAFP(更容易要求宽恕而不是允许)原则上工作。也就是说,无需指定接受一个ICloseno
ICloseable对象,而是close
在需要时尝试尝试该对象,如果它引发异常,则引发异常。
因此,以这种心态,您只需单独编写类,然后按需使用即可。如果其中之一不符合要求,则您的程序将引发异常。相反,如果您使用正确的方法编写另一个类,则它将正常工作,而无需指定它实现您的特定接口。
这很好用,但是有明确的接口用例,尤其是在大型软件项目中。Python的最终决定是提供该abc
模块,该模块允许您编写
抽象基类, 即除非您重写其所有方法,否则无法实例化的类。您是否应该使用它们是您的决定。
引入ABC的PEP解释比我能做的更好:
在面向对象编程领域,与对象交互的使用模式可以分为两个基本类别,即“调用”和“检查”。
调用是指通过调用对象的方法与对象进行交互。通常,这与多态性结合在一起,因此,调用给定方法可能会根据对象的类型运行不同的代码。
检查是指外部代码(在对象的方法之外)检查该对象的类型或属性,并根据该信息来决定如何处理该对象的能力。
两种使用模式均服务于相同的通用目的,即能够以统一的方式支持处理多种多样且可能新颖的对象,但同时允许为每种不同类型的对象定制处理决策。
在经典的OOP理论中,调用是首选的使用模式,并且不鼓励检查,因为检查被认为是较早的过程编程风格的产物。但是,实际上,这种观点过于教条和僵化,并导致一种设计僵化,与诸如Python之类的语言的动态特性大相径庭。
特别是,通常需要以对象类的创建者无法预期的方式处理对象。内置到满足该对象的每个可能用户需求的每个对象方法中,并非总是最佳的解决方案。此外,有许多强大的调度哲学与经典的OOP行为(严格地封装在一个对象中)形成了鲜明的对比,行为是规则或模式匹配驱动的逻辑。
另一方面,经典的OOP理论家对检查的批评之一是缺乏形式主义和所检查内容的特殊性质。在诸如Python这样的语言中,几乎可以通过外部代码反映并直接访问对象的任何方面,有很多不同的方法来测试对象是否符合特定的协议。例如,如果询问“此对象是可变序列容器吗?”,则可以寻找“列表”的基类,或者可以寻找名为“
getitem”的方法。但请注意,尽管这些测试看似显而易见,但它们都不是正确的,因为其中一个会产生假阴性,而另一个会产生假阳性。普遍同意的补救措施是对测试进行标准化,并将其分组为正式形式。通过继承机制或其他某种方式,通过与每个类关联一组标准的可测试属性,最容易做到这一点。每个测试都带有一组诺言:它包含有关类的一般行为的诺言,以及关于其他可用的类方法的诺言。
该PEP为组织这些测试提出了一种特殊的策略,称为抽象基类(ABC)。ABC只是添加到对象继承树中的Python类,以将对象的某些功能发送给外部检查器。使用isinstance()完成测试,并且特定ABC的存在意味着测试已通过。
此外,ABC定义了建立类型特征行为的最少方法集。根据对象的ABC类型区分对象的代码可以相信,这些方法将始终存在。这些方法中的每一个都附带有通用的抽象语义定义,该定义在ABC的文档中进行了描述。这些标准的语义定义不是强制性的,但强烈建议使用。
像Python中的所有其他内容一样,这些承诺属于绅士协议的性质,在这种情况下,这意味着尽管该语言确实执行了ABC中做出的某些承诺,但具体类的实现者必须确保其余的保留下来。
问题内容: 考虑一个示例(在Java中编译) 为什么必须将接口“声明”为抽象的?还有其他适用于抽象接口的规则吗? 最后:如果过时了,为什么将它包含在Java中?有抽象接口的历史吗? 问题答案: 为什么必须将接口“声明”为抽象的? 不是。 接口及其方法是隐式的,添加该修饰符没有区别。 还有其他适用于抽象接口的规则吗? 不,适用相同的规则。该方法必须由任何(具体)实现类来实现。 如果抽象已经过时,为什
问题内容: 在面试中,有人问我以下问题。我试图回答这个问题,但是我想确切回答这个问题。 如果我可以将Abstract类模拟为Interface,为什么Java提供了Interface? 这意味着如果在Abstract类中我可以将所有方法标记为abstract,然后abstract类将用作接口,那么为什么我需要接口。 谁能简单地解释一下我。 问题答案: 这是一个非常标准的面试问题。答案是:因为您可以
我想读关于抽象的文章,但读到不同的文章,我感到很困惑。 下面是我无法理解的问题: 1)“抽象是通过使用抽象类和接口实现的吗?”我对此进行了搜索,得到了三种类型的答案: 与此处解释的不同。 它们是相同的,只是不同的观点,就像这里解释的。 最后一个是抽象类用来实现抽象。 哪一个是真的?请举一个简单的例子。 2)“抽象意味着隐藏不必要的细节。比如专注于一个对象做什么而不是它是如何完成的。” 这是正确的吗
现在,我们知道Java 8在接口中引入了默认和静态方法。 接口最初在Java中引入是为了避免C++中出现的菱形问题,在多重继承中。 但是,随着Java8在接口中引入默认方法,现在,Java也引入了菱形问题,它在以前的版本中避免了这个问题。 默认方法不是必须重写的。 但是当使用接口发生菱形问题时,实现这些接口的类必须重写默认方法。 null PS我在互联网上没有找到任何关于这方面的好文章的链接。 他
问题内容: Python中的抽象类和接口有什么区别? 问题答案: 有时您会看到以下内容: 因为Python没有(也不需要)正式的Interface协定,所以抽象和接口之间不存在Java风格的区别。如果有人努力定义一个正式的接口,它也将是一个抽象类。唯一的区别在于文档字符串中所述的意图。 当您进行鸭类输入时,抽象和接口之间的区别是令人不解的事情。 Java使用接口是因为它没有多重继承。 由于Pyth
问题内容: 我被问到一个问题,我想在这里让我的答案复习。 问:在哪种情况下,扩展抽象类而不是实现接口更合适? 答:如果我们使用模板方法设计模式。 我对么 ? 很抱歉,如果我不能清楚地说明问题。 我知道抽象类和接口之间的基本区别。 1)在要求如此的情况下使用抽象类,即我们需要为特定操作(实现方法)在每个子类中实现相同的功能,而为某些其他操作(仅方法签名)实现不同的功能 2)如果需要使签名相同(且实现