day6-类的继承
概述
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
继承的过程,就是从一般到特殊的过程。
要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。
在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。
继承概念的实现方式主要有2类:实现继承、接口继承。
OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。
类的继承
不带参数的继承
1.继承的定义
用法:在类名的括号中写入需要继承的类名即可
class Person(object): def talk(self): print("person is talking.....") class BlackPerson(Person): #继承Person这个类 def walk(self): #定义子类自身的walk方法 print("black person is blaaa......") b = BlackPerson() b.talk() #由于继承了父类的talk()方法,所以可以被调用 b.walk() #调用子类自身的walk方法 #输出 person is talking..... black person is blaaa......
2.子类对父类方法的重写
class Person(object): #定义person类 def talk(self): #定义方法talk print("person is talking.....") class BlackPerson(Person): #继承Person类 def walk(self): #定义自己的方法 print("black person is blaaa......") def talk(self): #重写父类 print("black person is talking ... ") b = BlackPerson() b.talk() b.walk() #输出 black person is talking ... black person is blaaa......
解析:如果在子类BlackPerson中重写了父类的方法,那么就调用子类的方法,子类中没有对父类方法进行重写的话,那么就调用父类的方法,这就是继承。
带参数的继承
构造方法的继承
用法:因为子类有自己的属性,但是又想继承父类的属性,所以需要先继承,再重构
继承类的构造方法2种写法:
- 经典类写法:父类.__init(self,name,age)
- 新式类写法:super(子类,self).__init__(name,age)
注:建议使用新式类的写法,因为使用经典类的写法,在多继承的情况下,会出现重复调用参数的可能
class Person(object): #定义person类 def __init__(self,name,age): self.name = name self.age = age def talk(self): #定义方法talk print("person is talking.....") class BlackPerson(Person): #继承Person类 def walk(self): #定义自己的方法 print("black person is blaaa......") def talk(self): #重写父类 print("black person is talking ... ") b = BlackPerson() b.talk() b.walk() #输出 Traceback (most recent call last): File "C:/Users/huwei/PycharmProjects/module_2/类的继承.py", line 19, in <module> b = BlackPerson() TypeError: __init__() missing 2 required positional arguments: 'name' and 'age'
解析:在这儿为什么报错?从报错信息中可以看出,没有参数的传入,为什么报错?因为在BlackPerson里面没写构造函数,那么子类BlackPerson就继承父类的,而父类的构造函数要求必须有参数传入,而这时,子类没有参数传入,因此,出现报错。
接着,我们对调用进行修改
b = BlackPerson("Dick",20)即可。
再者,如果我们想要同时继承父类的方法,且子类又想增加别的构造函数,怎么办?通过一个例子来说说先继承,再重构:
class Person(object): #定义person类 def __init__(self,name,age): #形式参数 self.name = name #self = b ---> self.name = b.name self.age = age self.sex = "normal" #默认的,不需要传参数进来 def talk(self): #定义方法talk print("person is talking.....") class BlackPerson(Person): #继承Person类 #先继承,再重构↓ def __init__(self,name,age,strenth): #1 定义时需要传入父类的属性名 Person.__init__(self,name,age) #继承父类的构造方法 #经典类 #super(BlackPerson,self).__init__(name,age) #新式类(推荐) self.strenth = strenth #定义子类本身的属性 print(self.name,self.age,self.strenth) def walk(self): #定义自己的方法 print("black person is blaaa......") def talk(self): #重写父类 Person.talk(self) print("black person is talking ... ") class WhitePerson(Person): pass b = BlackPerson("Dick",28,"strong") #输出 Dick 28 strong
#经典类与新式类,选其一
这里有一个疑问?我们为什么不能在子类中重新写一遍,为什么要继承父类中的方法(构造函数)呢?因为你重新写一遍的话,#1处因为我们只传进来name和age,所以只能继承self.name和self.age,那self.sex怎么办,它也需要重写吗?所以,只有把父类中的构造函数全部继承过来,使用先继承,再重构的方法,下面是调用的流程:
解析:b对象通过BlackPerson实例化后,虽然BlackPerson构造函数继承了父类的,但是我们对其进行了先继承后重构,所以,当我们实例化时对子类本身形参进行了调用,实际上子类本身的形参将其自己传给了父类的构造函数,self = b,所以能够打印出name,age,sex。
类的继承实例
单继承
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):
"""注册"""
print("just enrolled a new school member [%s]" %self.name)
SchoolMember.member +=1
def tell(self):
print("------%s-------"%self.name)
for k,v in self.__dict__.items():
print("\t",k,v)
print("===end===")
def __del__(self):
print("开除了[%s]..."%self.name)
SchoolMember.member -=1
class Teacher(SchoolMember):
"""讲师类"""
def __init__(self,name,age,sex,salary,course):
# SchoolMember.__init__(self,name,age,sex) #经典类写法
super(Teacher, self).__init__(name,age,sex) #新式类写法
self.salary = salary
self.course = course
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
self.amount = 0
def paytuition(self,amount):
print("student [%s] has just paied [%s]"%(self.name,amount))
self.amount +=amount
t1 = Teacher("Dick",28,"M",3000,"Python")
s1 = Student("Sophie",25,"F","SAP",18000)
s2 = Student("Jacky",25,"M","SAP",15000)
print(SchoolMember.member)
t1.tell()
s2.tell()
del s2
print(SchoolMember.member)
#输出
just enrolled a new school member [Dick]
just enrolled a new school member [Sophie]
just enrolled a new school member [Jacky]
3
------Dick-------
salary 3000
course Python
name Dick
age 28
sex M
===end===
------Jacky-------
course SAP
amount 0
tuition 15000
name Jacky
age 25
sex M
===end===
开除了[Jacky]...
2
开除了[Dick]...
开除了[Sophie]...