将通用方法放入Python中的抽象类是一种好习惯吗?

时间:2018-11-08 17:56:13

标签: python inheritance abstract-class

我正在使用abc模块来定义子类必须支持的接口。在所有子类中也存在一些通用方法。可以将它们放在抽象类中还是应该只包含抽象方法(即用@abc.abstractmethod装饰)?

1 个答案:

答案 0 :(得分:3)

TL; DR; 是的,抽象类具有非抽象方法是可以的。

我们通常所说的抽象类只是一个无法实例化的类。

另一方面,我们所说的一个接口是一个只有方法声明而没有实现的类。特别是它的抽象类,因为它没有构造函数。

当然在Python中没有真正的接口:每个方法都必须有一个主体。但是我们可以通过raise NotImplementedError()来模拟接口。

任何接口都构成抽象类的子集。这显然表明存在不是接口的抽象类。这正是您所描述的情况。是的,抽象类可能包含已实现的非抽象方法。这不是一个坏习惯。当给定方法不依赖于具体实现时,这特别有用。


例如考虑一个通用解析器的接口(我在考虑json.loadjson.loads):

class ILoader(ABC):
    @abstractmethod
    def load(self, stream):
        raise NotImplementedError()

使用默认实现为loads方法接受字符串而不是流是完全可以的:

class AbstractLoader(ABC):
    @abstractmethod
    def load(self, stream):
        raise NotImplementedError()

    def loads(self, text):
        stream = io.StringIO(text)
        return self.load(stream)

尽管我会使用Abstract前缀而不是I。 ;)