day6-类继承
一、 概念
之前我们说到了类的公有属性和类的私有属性,其实就是类的封装。而类的继承是指可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”,继承的过程,就是从一般到特殊的过程。在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。
继承概念的实现方式主要有2类:实现继承、接口继承。
a. 实现继承是指使用基类的属性和方法而无需额外编码的能力。
b. 接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力(子类重构爹类方法)。
在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。
抽象类仅定义将由子类创建的一般属性和方法,OO开发范式大致分为如下阶段:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现
二、继承
1 class Person(object): 2 3 def __init__(self,name,age): 4 self.name = name 5 self.age = age 6 self.addr = "sz" 7 8 def talk(self,number): 9 print("person is talking..."+number) 10 11 # 继承Person这个类 12 class BlackPerson(Person): 13 14 # 既想继承属性,又想拥有自身属性,需要先继承,再重构 15 # 定义时需要传入父类的属性名 16 def __init__(self,name,age,strength): 17 # 继承父类的构造方法 18 # 经典类写法:父类.__init__(self, 属性名) 19 # 新式类写法:super(子类,self).__init__(属性名) 20 # super(BlackPerson,self).__init__(name,age) 21 Person.__init__(self,name,age) 22 # 定义子类本身的属性 23 self.strength = strength 24 print(self.name,self.age,self.addr) 25 26 # 定义子类自身的walk方法 27 def walk(self): 28 print("BlackPerson is walking.....") 29 30 # 重写父类的方法 31 # 重写方法的方法名必须和父类中被重写的方法名一模一样 32 # 重写方法的传入的参数名和参数的个数必须和父类中被重写的方法一样 33 def talk(self, number): 34 # 调用父类的方法 35 Person.talk(self, number) 36 print("BlackPerson is talking ..."+number) 37 38 39 b = BlackPerson("bk",24,"strong") 40 # 继承父类的talk()方法 41 b.talk("1") 42 # 调用子类自身的walk方法 43 b.walk() 44 45 bk 24 sz 46 person is talking...1 47 BlackPerson is talking ...1 48 BlackPerson is walking.....
三、实例
1 # coding:gbk 2 3 4 class SchoolMember(object): 5 """学校成员基类""" 6 7 # 设置公有属性 8 member = 0 9 10 def __init__(self, name, age, sex): 11 self.name = name 12 self.age = age 13 self.sex = sex 14 # 生成对象时自动注册 15 self.enroll() 16 17 def enroll(self): 18 """注册""" 19 print("just enroll a new school member [{0}]".format(self.name)) 20 SchoolMember.member += 1 21 22 def tell(self): 23 print("------info:{0}-----".format(self.name)) 24 # self._dict__()函数是获取对象的属性,以字典的形式返回 25 for k, v in self.__dict__.items(): 26 print("\t", k, v) 27 print("------end--------") 28 29 def __del__(self): 30 print("delete[{0}]...".format(self.name)) 31 SchoolMember.member -= 1 32 33 34 class Teacher(SchoolMember): 35 """讲师类""" 36 37 def __init__(self, name, age, sex, salary, course): 38 SchoolMember.__init__(self, name, age, sex) 39 self.salary = salary 40 self.course = course 41 42 def teaching(self): 43 """讲课方法""" 44 print("Teacher [{0}] is teaching [{1}]".format(self.name, self.course)) 45 46 47 class Student(SchoolMember): 48 """学生类""" 49 def __init__(self, name, age, sex, couser, tuition): 50 SchoolMember.__init__(self, name, age, sex) 51 self.couser = couser 52 self.tuition = tuition 53 self.amount = 0 54 55 def pay_tuition(self, amount): 56 print("student [{0}] has just paied [{1}]".format(self.name, amount)) 57 self.amount += amount 58 59 # 注册3个成员 60 t1 = Teacher("zuoyi", 18, "F", 3000, "Python") 61 s1 = Student("zhaosan", 19, "M", "PYS15", 300000) 62 s2 = Student("lisi", 12, "M", "PYS15", 11000) 63 64 print(SchoolMember.member) 65 # 删除成员s1的引用,c此时会主动调用析构函数 66 del s1 # 删除一个变量 67 t1.tell() 68 s2.tell() 69 70 print(SchoolMember.member) 71 # 当对象在某个作用域中调用完毕,在跳出其作用域的同时析构函数也会被调用一次,这样可以用来释放内存空间 72 # t1、s2调用完毕,整个程序退出,析构函数被调用 73 74 just enroll a new school member [zuoyi] 75 just enroll a new school member [zhaosan] 76 just enroll a new school member [lisi] 77 3 78 delete[zhaosan]... 79 ------info:zuoyi----- 80 age 18 81 name zuoyi 82 salary 3000 83 course Python 84 sex F 85 ------end-------- 86 ------info:lisi----- 87 amount 0 88 couser PYS15 89 age 12 90 name lisi 91 tuition 11000 92 sex M 93 ------end-------- 94 2 95 delete[zuoyi]... 96 delete[lisi]...
四、 多继承
多继承:子类继承多个父类
1 class SchoolMember(object): 2 """学校成员基类""" 3 4 def tell(self): 5 print("the schoolmeber is tell...") 6 7 8 class School(object): 9 """学校类""" 10 11 def open_branch(self, addr): 12 print("openning a new branch in", addr) 13 14 15 # 子类Teacher同时继承了SchoolMember,School两个类 16 class Teacher(SchoolMember, School): 17 """讲师类""" 18 def teaching(self): 19 """讲课方法""" 20 print("Teacher outman is teaching python") 21 22 t1 = Teacher() 23 # 继承父类SchoolMember的tell方法 24 t1.tell() 25 # 继承父类School的open_branch方法 26 t1.open_branch("shanghai") 27 28 29 the schoolmeber is tell... 30 openning a new branch in shanghai
五、 新式类与经典类
1 # 新式类:继承object类 2 class Person(object): 3 "新式类" 4 pass 5 6 # 新式类初始化构造方法用super关键字去继承 7 # super(子类,self).__init__(name,age) 8 # 新式类多继承的调用顺序:广度优先搜索 9 # D-B-C-A 10 11 12 class A(object): 13 def __init__(self): 14 self.n = "A" 15 16 class B(A): 17 # pass 18 def __init__(self): 19 self.n = "B" 20 21 class C(A): 22 # pass 23 def __init__(self): 24 self.n = "C" 25 26 class D(B,C): 27 # pass 28 def __init__(self): 29 self.n = "D" 30 31 d = D() 32 print(d.n) 33 34 a. 直接运行 35 输出:D 36 b. 删除D的init方法 37 输出:B 38 c. 删除D和B的init方法 39 输出:C 40 d. 删除D、B、C的init方法 41 输出:A
上述程序的广度查询顺序:

1 # 经典类:不继承任何类 2 class Person: 3 "经典类" 4 pass 5 6 # 经典类初始化构造方法父类.__init(self,name,age) 7 # 经典类多继承的调用顺序:深度优先搜索 8 # D-B-A-C 9 10 11 class A: 12 # pass 13 def __init__(self): 14 self.n = "A" 15 16 class B(A): 17 # pass 18 def __init__(self): 19 self.n = "B" 20 21 class C(A): 22 def __init__(self): 23 self.n = "C" 24 25 class D(B,C): 26 # pass 27 def __init__(self): 28 self.n = "D" 29 30 d = D() 31 print(d.n) 32 33 a. 直接运行 34 输出:D 35 b. 删除D的init方法 36 输出:B 37 c. 删除D和B的init方法 38 输出:A 39 d. 删除D、B、A的init方法 40 输出:C
上述程序的深度查询顺序:

小结:
1. 新式类继承object类,经典类不继承任何类
2. 新式类用super关键字继承构造方法super(子类,self).__init__(属性),经典类用 父类.__init__(self,属性)来继承
3. 新式类:广度优先搜索,经典类:深度优先搜索
4. Python2才有上述之分,Python3中不管是经典类还是新式类均采用广度优先搜索

浙公网安备 33010602011771号