# 这是学习廖雪峰老师python教程的学习笔记

1、概览

在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。

1.1、父类与子类的关系

  • 子类可以继承父类的方法

  • 子类的a方法 父类的a方法同名,则子类的a方法会 覆盖 父类的a方法

  • 子类定义instance,既是子类的数据类型,又是父类的数据类型。反过来不行。【这叫多态】

 

  1. 定义一个类Animal,其中有方法 run()

class Animal(object):
   
def run(self):
        print(
'Animal is running...')

  1. 定义一个子类Dog,其中也有方法 run()

class Dog(Animal):
def run(self):
        print(
'Dog is running...')

  1. 验证方法的继承

>>> Dog().run() #  Dog表示classDog()表示instance。且每次Dog() 创造的实例不同

Dog is running...

  1. 定义一个使用Anmial 数据类型的 函数

def run_twice(animal):
    animal.run()

  1. 对比Animal() Dog() 的不同

>>> run_twice(Animal())

Animal is running…

 

>>> run_twice(Dog())

Dog is running...

 

  1. 总结

对而言,run_twice()不做任何修改,任何依赖Animal作为参数的函数或者方法都可以不加修改地正常运行,原因就在于多态。

1.2、开闭原则

调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管原来的代码是如何调用的。

  • 对扩展开放:允许新增Animal子类;

  • 对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。

 

2、静态语言 VS 动态语言

对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。

 

对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了。

class Timer(object):
   
def run(self):
        print(
'Start...')

 

# 调用结果

>>> run_twice(Timer())

Start…

 

这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。只要你的 方法一样,不一定要传入真正符合数据类型的对象