Python的继承

继承是面向对象编程(OOP)的一个重要的概念。继承附于了类一种能力:它可以使用现有类的所有属性方法等代码和逻辑而无需编写重复的代码,在需要的时修还可以对这些已有的功能进行扩展。

通过继承创建的新类称为子类派生类,被继承的类称为基类父类超类,继承的过程,就是从一般到特殊的过程。继承反映了编程事物在现实世界中的真实关系,使用代码变得更易于理解和维护,这也是面向对象编程能够流行起来的一个重要的原因。

继承可以分为:类继承和接口继承。

  • 类继承是指从类继承,其基类是一个类。子类可以使用基类的属性和方法而无需额外编码。

    根据类是否支持继承基类,可以将继承分为单继承和多继承。在现有的OOP语言中,有的支持单继承,有的支持多继承,Python是一种支持多继承的语言。

  • 接口继承是指从接口继承,接口仅定义了子类应实现的属性和方法,子类必须提供这些实现这些父接口规定的属性和方法。

    Python不支持接口,但经常会使用类来模仿这种编程思想。

在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Animal类用于表示是动物,Dog也是属于一种动物,因此Dog可以继承Animal类。但是Banyan(榕树)类不能继承Animal类,因为榕树不属于一种动物。

继承使用基类(父类)的形式实现。

class Animal(object):   # 定义一个父类

    def breathe(self):  # 父类中的方法,这是Animal类的共性
        print("动物都会呼吸!")  

class Dog(Animal):    # 定义一个子类, 继承Animal类

    def call(self):   # 在子类中定义其自身的方法,这是Dog类的特性
        print('汪汪...')

if __name__=='__main__':
    c = Dog()
    c.breathe()     # 调用从Animal类继承的方法
    c.call()        # 调用Dog本身实现的方法

运行后,输出如下结果:

动物都会呼吸!
汪汪...

构造函数的继承

因为Python都是在构造函数中定义属性的,在不重写构造函数__init__方法时,会自动的调用父类的构造函数。当子类重写了构造函数__init__方法时,为了继承父类的属性,应该在子类的构造函数中调用父类的构造函数。

调用父类构造函数的方法:

super(子类,self).__init__(参数1,参数2,....)

还有一种经典的写法:

父类名称.__init__(self,参数1,参数2...)

下面我改造一下前面的示例:

class Animal(object):  

    def __init__(self, name):
        self.name=name
        print ( "动物的名字是: %s" %( self.name) ) 

    def breathe(self):  
        print("动物都会呼吸!")  

class Dog(Animal):    

    def __init__(self, name):
        super(Dog, self).__init__(name)

    def call(self):   
        print('汪汪...')

if __name__=='__main__':
    c = Dog("No.1")

输出如下结果:

动物的名字是: No.1

如果我们只是简单的在子类Dog中定义一个构造函数,其实这是在重写父类的构造函数。这样子类是不能继承父类的属性的。所以我们在定义子类的构造函数时,必须显示调用父类的构造函数,这样我们也能使用父类的属性了。

重写父类的方法

对于父类的方法,只要它不符合子类的行为,都可以进行重写。我们只需在子类中定义一个与要重写的父类方法同名的方法。这样,实例化子类后,调用这个方法,Python实际执行的是子类方法。

class Animal(object):  

    def breathe(self):  
        print("我用肺呼吸!")  

class Fish(Animal):    

    def breathe(self):  
        print("我用鳃呼吸!") 

if __name__=='__main__':
    c = Fish()
    c.breathe()

运行后,输出:

我用鳃呼吸!