python中的继承和多态(ABCMeta模块)

在已有类的基础上创建新类,其中的一个做法就是让一个类从另一个类那里将属性和方法直接继承下来,从而减少重复代码的编写。提供继承信息的我们称之为父类,也叫超类或基类;得到继承信息的我们称之为子类,也叫派生类或衍生类。子类除了继承父类提供的属性和方法,还可以定义自己特有的属性和方法,所以子类比父类拥有更多的能力。在实际开发中,我们经常会用子类对象去替换掉一个父类对象,这是面向对象编程中一个常见的行为,对应的原则称之为里氏替换原则。下面我们先看一个继承的例子。

class Person(object):
    '''人'''
    
    def __init__(self, name, age):
        self._name = name
        self._age = age
    
    @property
    def name(self):
        return self._name
    
    @property
    def age(self):
        return self._age
    
    @age.setter
    def age(self, age):
        self._age = age
    
    def play(self):
        print('%s正在和狗愉快的玩。' % self._name)
    
    def watch_movie(self):
        if self._age >= 18:
            print('%s可以看恐怖电影。'% self._name)
        else:
            print('%s因为小于18岁,所以只能看动漫。'% self._name)

class Student(Person):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self._grade = grade
    
    @property
    def grade(self):
        return self._grade
    
    @grade.setter
    def grade(self, grade):
        self._grade = grade
    
    def study(self,course):
        print('{}的{}正在学习{}'.format(self._grade, self._name, course))


class Teacher(Person):
    def __init__(self, name, age, title):
        super().__init__(name, age)
        self._title = title
    
    @property
    def title(self):
        return self._title
    
    @title.setter
    def title(self, title):
        self._title = title
    
    def teach(self, course):
        print("{}{}正在讲{}课。".format(self._name, self._title, course))


def main():
    stu = Student('大锤',13,'初中')
    stu.study('语文')
    stu.watch_movie()
    stu._age = 18
    stu.watch_movie()
    teacher = Teacher('张三', 38, '老师')
    teacher.teach('数学')
    teacher.play()
    teacher.watch_movie()


if __name__ == "__main__":
    main()

子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)。

from abc import ABCMeta, abstractmethod

class Pet(object, metaclass=ABCMeta):
    
    def __init__(self, nickname):
        self._nickname = nickname
    
    @abstractmethod
    def make_voice(self):
        '''发出声音'''
        print('123')

class Dog(Pet):
    '''狗'''
    def make_voice(self):
        print('{}:汪汪汪~~~'.format(self._nickname))
    
def main():
    pet = Dog('lala')
    pet.make_voice()
    # pet = Pet('lala') #TypeError: Can't instantiate abstract class Pet with abstract methods make_voice
    # pet.make_voice() #TypeError:无法用抽象方法实例化抽象类Pet

if __name__ == "__main__":
    main()

在上面的代码中,我们将Pet类处理成了一个抽象类,所谓抽象类就是不能够创建对象的类,这种类的存在就是专门为了让其他类去继承它。Python从语法层面并没有像Java或C#那样提供对抽象类的支持,但是我们可以通过abc模块的ABCMeta元类和abstractmethod包装器来达到抽象类的效果,如果一个类中存在抽象方法那么这个类就不能够实例化(创建对象)。上面的代码中,Dog和Cat两个子类分别对Pet类中的make_voice抽象方法进行了重写并给出了不同的实现版本,当我们在main函数中调用该方法时,这个方法就表现出了多态行为(同样的方法做了不同的事情)。

你可能感兴趣的:(python中的继承和多态(ABCMeta模块))