继承和多态
# 继承
# 父类,基类&& 子类,派生类
面向对象编程的一大优点是对代码的重用(Reuse), 重用的一种实现方法就是通过继承 (Inheritance)机制。继承最好是想象成在类之间实现类型与子类型(Type and Subtype) 关系的工具。
SchoolMember 类会被称作基类(Base Class)4或是超类 (Superclass)。 Teacher 和 Student 类会被称作派生类(Derived Classes)5或是子类 (Subclass)
class SchoolMember:
"""父类, 学校成员类"""
def __init__(self, name, age):
self.name = name
self.age = age
print('init SchoolMember: {}'.format(self.name), end=' ')
def tell(self):
print('name:{}, age: {}'.format(self.name, self.age))
class Teacher(SchoolMember):
"""老师类"""
def __init__(self, name, age, salary):
SchoolMember.__init__(self, name, age)
self.salary = salary
print('init teacher:{}'.format(self.name))
def tell(self):
SchoolMember.tell(self)
print('salary:{:d}'.format(self.salary))
class Student(SchoolMember):
"""学生类"""
def __init__(self, name, age, id):
SchoolMember.__init__( self, name, age)
self.id = id
print('init student:{}'.format(self.name))
def tell(self):
SchoolMember.tell(self)
print('id: {}'.format(self.id))
t = Teacher('teacher AAAAAA', 38, 6000)
s = Student('student BBBBBB',12, 'student')
members = [t, s]
for member in members:
member.tell()
SchoolMember
是父类, Teacher
和 Student
类是子类。
类的继承的语法是,
- 子类的定义要加上父类的类名
class Student(SchoolMember):
/class Teacher(SchoolMember):
- 然后,我们会注 意到基类
__init__
方法是通过self
变量被显式调用的,因此我们可以初始化对象的基类部分。 下面这一点很重要,需要牢记——因为我们在 Teacher 和 Student 子类中定义了__init__
方法,Python 不会自动调用基类SchoolMember
的构造函数,你必须自己显式地调用它,SchoolMember.__init__( self, name, age)
。 相反,如果我们没有在一个子类中定义一个__init__
方法,Python 将会自动调用基类的构 造函数。
当我们使用 SchoolMember
类的 tell
方法时,我们可以将 Teacher 或 Student 的实例看作 SchoolMember
的实例。SchoolMember.tell(self)
同时,你会发现被调用的是子类型的 tell
方法,而不是 SchoolMember
的 tell
方法。
理解这一问题的一种思路是 Python 总会从当前的实际类型中开始寻找方法,在本例中即是如
此。如果它找不到对应的方法,它就会在该类所属的基本类中依顺序逐个寻找属于基本类的
方法,这个基本类是在定义子类时后跟的元组指定的。
这里有一条有关术语的注释——如果继承元组(Inheritance Tuple)中有超过一个类,这种情
况就会被称作多重继承(Multiple Inheritance)。
# 多态
有几个规则需要知道,
- 如果函数需要的是
Animal
类型, 不需要知道是否是Animal
或者它的子类型Dog
/Cat
等, 这就是多态 - 开闭原则
- 动态语言的 鸭子类型,通俗的讲,是不需要准确的类型匹配。