目录
继承
我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)
子类继承了父类的的属性和方法。继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。
比如下方这个代码,Student类继承了Person类,通过Student实例化的对象中包含了Person类中的属性和方法。
class Person(object):
def __init__(self,name,age):
if type(name) is str:
self.__name = name
else:
raise TypeError('should be str')
if ((age < 0) | (age > 300)):
raise ValueError('should be in (0~301)')
elif (type(age) is not int):
raise TypeError('should be int')
else:
self.__age = age
def print_name(self):
print(self.__name)
def print_age(self):
print(self.__age)
class Student(Person):
def sta_studing(self):
print('student studing...')
pass
stu1 = Student('forest',23)
stu1.print_name()
stu1.print_age()
stu1.sta_studing()
多态
当子类和父类都有同一个方法时,子类的方法覆盖父类的方法,程序运行时都会调用子类的方法。
我们知道,一个类其实就是一个数据类型,比如前文的
person1 = Person('liwei',22,164)
这里的person1就是Person类型,而Person的子类Student类实例化的对象stu1是什么类型?
person1 = Person('liwei',22,164)
stu1 = Student('forest',23,165)
print(isinstance(person1,Person))
print(isinstance(stu1,Person))
print(isinstance(stu1,Student))
可以看到stu1既是Person类型也是stu类型,就像一个学生对象,既既是人类,也是学生。这就是多态!
对于一个变量,我们只需要知道它是某个类型,无需确切地知道它的子类型,就可以放心地调用它的方法,而具体调用的方法是作用该类型对象上还是其子类对象上,由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种该类型的子类时,只要确保子类中该方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则:
对扩展开放:允许新增子类;
对修改封闭:不需要修改依赖该类型的函数,因为其子类是也是同时是该类型。(比如,学习语言这种方法,人类可以用,学生一样可以用。【这学生类就是人类的子类,人类是学生类的父类】)
静态语言和动态语言
对于静态语言(例如Java)来说,如果需要传入某个类型,则传入的对象必须是该类型或者它的子类,否则,将无法调用其方法。
对于Python这样的动态语言来说,则不一定需要传入该类型。我们只需要保证传入的对象有一个该方法就可以了。
动态语言的“鸭子类型”:它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。