“不能实例化抽象类……使用抽象方法"在不应该有任何抽象方法的类上 [英] “Can't instantiate abstract class … with abstract methods” on class that shouldn't have any abstract method

查看:36
本文介绍了“不能实例化抽象类……使用抽象方法"在不应该有任何抽象方法的类上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以以下最小示例为例:

import abc

class FooClass(object):
  __metaclass__ = abc.ABCMeta

  @abc.abstractmethod
  def FooMethod(self):
    raise NotImplementedError()


def main():
  derived_type = type('Derived', (FooClass,), {})

  def BarOverride(self):
    print 'Hello, world!'
  derived_type.FooMethod = BarOverride

  instance = derived_type()

运行 main() 让你:

TypeError: Can't instantiate abstract class Derived with abstract methods FooMethod

(异常发生在 instance =derived_type() 行.)

(The exception occurs on the instance = derived_type() line.)

但是FooMethod 不应该是抽象的:我已经用BarOverride 覆盖了它.那么,为什么这会引发异常?

But FooMethod shouldn't be abstract: I've overridden it with BarOverride. So, why is this raising exceptions?

免责声明: 是的,我可以使用显式的 class 语法,并完成完全相同的事情.(更好的是,我可以让它工作!)但这是一个最小的测试用例,更大的例子是动态创建类.:-) 我很好奇为什么这不起作用.

Disclaimer: Yes, I could use the explicit class syntax, and accomplish the exact same thing. (And even better, I can make it work!) But this is a minimal test case, and the larger example is dynamically creating classes. :-) And I'm curious as to why this doesn't work.

并防止其他明显的非答案:我不想将 BarOverride 在第三个参数中传递给 type: 在实际例子中,BarOverride 需要绑定 derived_type.如果我可以在创建 derived_type 之后定义 BarOverride,这样做会更容易.(如果我做不到,那为什么?)

And to prevent the other obvious non-answer: I don't want to pass BarOverride in the third argument to type: In the real example, BarOverride needs to have derived_type bound to it. It is easier to do this if I can define BarOverride after the creation of derived_type. (If I can't do this, then why?)

推荐答案

因为文档是这样说的:

动态地向类添加抽象方法,或尝试添加抽象方法创建方法或类后,修改其抽象状态,不支持.abstractmethod() 只影响子类使用常规继承派生;虚拟子类"注册ABC 的 register() 方法不受影响.

Dynamically adding abstract methods to a class, or attempting to modify the abstraction status of a method or class once it is created, are not supported. The abstractmethod() only affects subclasses derived using regular inheritance; "virtual subclasses" registered with the ABC’s register() method are not affected.

元类仅在定义类时调用.当 abstractmethod 将一个类标记为抽象时,该状态以后不会改变.

A metaclass is only called when a class is defined. When abstractmethod has marked a class as abstract that status won't change later.

这篇关于“不能实例化抽象类……使用抽象方法"在不应该有任何抽象方法的类上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆