继承
- 实现继承, 可以通过"继承"(Inheritance) 和 "组合"(Composition) 来实现.
- 在某些语言中, 一个子类可以继承多个基类, 但是一般情况下, 一个子类只能有一个基类, 要实现多重继承,可以通过多级继承来实现.
继承概念的实现方式主要有两类:
- 实现继承
- 实现继承是指使用基类的属性和方法而无需额外编码的能力
- 接口继承
- 接口继承是指仅使用属性和方法的名称, 但是子类必须提供实现的能力(子类重构父类方法)
- 注意:
- 在考虑使用继承时, 有一点需要注意, 两个类之间的关系应该是"属于"关系. 例如, employee是一个人, manager也是一个人. 因此这两个类都可以继承person类, 但是leg却不能继承person类.
- 抽象类仅定义将由子类创建的一般属性和方法
OO开发范式大致为:
- 划分对象 -> 抽象类 -> 将类组织成为层次化结构(继承和合成) -> 用类与实例进行设计和实现几个阶段
#!/usr/bin/python # -*- coding: utf-8 -*- # 直接继承父类方法 class Person(object): def talk(self): print("person is talking") class BlackPerson(Person): pass b = BlackPerson() b.talk() # 子类自己有独有方法 class Person(object): def talk(self): print("person is talking") class BlackPerson(Person): def walk(self): print("BlackPerson is walking") b = BlackPerson() b.talk() b.walk() # 子类重写父类方法 class Person(object): def talk(self): print("person is talking") class BlackPerson(Person): def talk(self): print("BlackPerson is talking") def walk(self): print("BlackPerson is walking") b = BlackPerson() b.talk() b.walk() # 传参 class Person(object): def __init__(self, name, age): self.name = name self.age = age def talk(self): print("person is talking") class BlackPerson(Person): def talk(self): print("BlackPerson is talking") def walk(self): print("BlackPerson is walking") class WhitePerson(Person): pass b = BlackPerson("will smith", 30) b.talk() b.walk() # 先继承,再重构 class Person(object): def __init__(self, name, age): self.name = name self.age = age self.sex = "normal" def talk(self): print("person is talking") class BlackPerson(Person): def __init__(self, name, age, strength): # 先继承,再重构 Person.__init__(self, name, age) # 把子类实例传到父类(父类引用指向子类对象) print(self.name, self.age, self.sex) print(strength) def talk(self): print("BlackPerson is talking") def walk(self): print("BlackPerson is walking") class WhitePerson(Person): pass b = BlackPerson("will smith", 30, "strong") b.talk() b.walk()
多继承
- 一个子类有多个父类
#!/usr/bin/python # -*- coding: utf-8 -*- """ 命名规范: 1. 类名每个单词都要首字母大写 2. 类名下面要写注释 """ class SchoolMember(object): """ 学校成员基类 """ member = 0 def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex self.enroll() def enroll(self): """ 注册 :return: """ print("just enrolled a new school memeber [%s]" % self.name) # self.member += 1 # 每新注册一个, 成员数加1. 这样写只是当前子类成员数加1;要想父类SchoolMember总成员数加1, 需得加到全局变量里. SchoolMember.member += 1 def tell(self): print('------------%s info ----------' % self.name) for k, v in self.__dict__.items(): # __dict__方法可以打印出类的所有变量 print(" ", k, v) print("end".center(33, "-")) def __del__(self): print("开除了[%s]" % self.name) SchoolMember.member -= 1 class School(object): """ 假装是另一个社团团员类(以便Teacher和Student能继承;否则School是个组织, Teacher/Student是不能继承的) """ def open_branch(self, addr): print("opening new branch in ", addr) class Teacher(SchoolMember, School): # 多继承 """ 讲师类 """ def __init__(self, name, age, sex, salary, course): # SchoolMember.__init__(self, name, age, sex) # 继承父类变量写法1. 又称经典类写法. super(Teacher, self).__init__(name, age, sex) # 继承父类变量写法2. 又称新式类写法. self.salary = salary self.course = course # self.enroll() # enroll()方法在每个子类里都需要, 可以直接写在父类里 def teaching(self): print("Teacher [%s] is teaching [%s]" %(self.name, self.course)) class Student(SchoolMember): def __init__(self,name, age, sex, course, tuition): SchoolMember.__init__(self, name, age, sex) self.course = course self.tuition = tuition # fee # self.enroll() # enroll()方法在每个子类里都需要, 可以直接写在父类里 self.amount = 0 def pay_tuition(self, amount): print("student [%s] has just paid [%s]" %(self.name, amount)) self.amount += amount t1 = Teacher("WuSir", 28, "FM", 3000, "Python") s1 = Student("HaiTao", 38, "M", "Py15", 300000) s2 = Student("LiChuang", 12, "M", "Py15", 11000) print(SchoolMember.member) t1.tell() s1.tell() t1.open_branch("SH")
经典类 VS 新式类
- 写法的不同
- 经典类继承父类变量用ParentClass.__init__; 新式类继承父类变量用super()
- 多继承时继承顺序的不同
- python3 没有不同, 经典类和新式类都是广度查找
- python2 : 经典类深度查找; 新式类广度查找
#!/usr/bin/python # -*- coding: utf-8 -*- """ 写法不同: 1. 新式类: super 2. 经典类: ParentClass.__init__ 现在都主要写新式类 """ class Person(object): # new style 新式类. 注: 括号里的object是一个基类. super(Person, self).__init__() # init括号里写父类的全部变量名 class Person: # classical style 经典类 ParentClass.__init__() # init括号里写父类的全部变量名 """ 多继承时继承顺序的区别 : 1. python3中无区别, 都是广度查找; 2. python2中有区别(经典类: 深度查找. 若B注掉, 不会去找C,而是直接找A.A没有才再找回C; 新式类: 广度查找.) """ class A(object): def __init__(self): self.n = "A" class B(A): def __init__(self): self.n = "B" class C(A): def __init__(self): self.n = "C" class D(B, C): # 广度查找: 先把B,C找完, 找不到再找A; 深度查找: 找不到B, 直接去找A而不是C, A没有才找C. # def __init__(self): # self.n = "D" # 若打印print(d.n), 返回D. 就近原则 pass # 若打印print(d.n), 返回B d = D() print(d.n)