第11章-抽象类

ABC类

python中并没有提供抽象类与抽象方法,
但是提供了内置模块abc(abstract base class)来模拟实现抽象类。

可以通过abc将基类声明为抽象类的方式,然后注册具体类作为这个基类的实现。

假设我们在写一个关于动物的代码。涉及到的动物有鸟,狗,牛。

首先鸟,狗,牛都是属于动物的。既然是动物那么肯定需要吃饭,发出声音。

但是具体到鸟,狗,牛来说吃饭和声音肯定是不同的。

需要具体去实现鸟,狗,牛吃饭和声音的代码。

概括一下抽象基类的作用:定义一些共同事物的规则和行为

例子:

class Animal(object):
    def eat(self):
        raise NotImplementedError

    def voice(self):
        raise NotImplementedError


class Dog(Animal):
    def voice(self):
        print('wow....')


class Bird(Animal):
    def voice(self):
        print('jiji....')


class Cow(Animal):
    def voice(self):
        print('Oh.....')


if __name__ == "__main__":

    d = Dog()
    d.voice()
    d.eat()  # raise NotImplementedError

这样实现有个缺点,就是只有子类调用eat方法的时候才会报错。

子类是可以正常实例化的。

但是你能够想象鸟,狗,牛不会吃饭么? 如果不会吃饭那肯定不算是动物了。

所以正常的实现应该是如果没有实现eat方法,实例化就应该是失败的。

那么这里就要用到抽象基类的一般使用方法.

import abc


class Animal(object):

    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def eat(self):
        return

    @abc.abstractmethod
    def voice(self):
        return


class Dog(Animal):
    def voice(self):
        print('wow....')

    def eat(self):
        print("Dog eat...")


class Bird(Animal):
    def voice(self):
        print('jiji....')

    def eat(self):
        print("Bird eat...")


class Cow(Animal):
    def voice(self):
        print('Oh.....')

    def eat(self):
        print("Cow eat...")


if __name__ == "__main__":

    d = Dog()
    b = Bird()
    c = Cow()

    d.voice()
    d.eat()

    b.voice()
    b.eat()

    c.voice()
    c.eat()

返回结果:

wow....
Dog eat...
jiji....
Bird eat...
Oh.....
Cow eat...

使用注册的方式:

from abc import ABCMeta, abstractmethod


class Animal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):
        return

    @abstractmethod
    def voice(self):
        return


class Dog(object):
    def voice(self):
        print('wow....')

    def eat(self):
        print("Dog eat...")


# 使用注册方式,必须两个方法都要写,否则会报错
Animal.register(Dog)

if __name__ == "__main__":

    d = Dog()

    d.voice()
    d.eat()


继承和注册这两种方法有什么区别呢?

animals.py

from abc import ABCMeta, abstractmethod


class Animal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):
        return

    @abstractmethod
    def voice(self):
        return

sub_class.py

from animals import Animal


class Dog(Animal):
    def voice(self):
        print('wow....')

    def eat(self):
        print("Dog eat...")


print('subclass=', issubclass(Dog, Animal))
print('Instance=', isinstance(Dog(), Animal))

abc_register.py

from animals import Animal


class Dog(object):
    def voice(self):
        print('wow....')

    def eat(self):
        print("Dog eat...")


Animal.register(Dog)

print('subclass=', issubclass(Dog, Animal))
print('Instance=', isinstance(Dog(), Animal))

王知晓
37 声望19 粉丝

知晓知晓,上知天文下晓地理