DAY31继承派生、组合、接口和抽象类
来源:互联网 发布:淘宝贷款还不起怎么办 编辑:程序博客网 时间:2024/05/22 16:02
类的继承与派生
经典类和新式类
在python3中,所有类默认继承object,但凡是继承了object类的子类,以及该子类的子类,都称为新式类(在python3中所有的类都是新式类)
没有继承object类的子类成为经典类(在python2中,没有继承object的类,以及它的子类,都是经典类)
class People: passclass Animal: passclass Student(People,Animal): #People、Animal称为基类或父类,Student为子类,Student继承了People和Animal的所有属性 passprint(Student.__bases__) #__bases__方法,查看继承的类的元组print(People.__bases__)print(Animal.__bases__)
输出结果:
(
class People: #定义父类People def __init__(self, name, age): self.name = name self.age = age def walk(self): print('%s is walking' %self.name)#Teacher类和Student类无任何属性class Teacher(People): #Teacher类继承People类的属性 passclass Student(People): #Student类继承People类的属性 pass
引用测试:
t=Teacher('bob',18) #实例化一个Teacher对象,而非People对象,Student子类同理print(type(t)) print(t.name,t.age)print(t.__dict__)t.walk() #Teacher子类继承了People的属性,使得Teacher子类的对象能够调用到父类的属性输出结果:<class '__main__.Teacher'>bob 18{'name': 'bob', 'age': 18}bob is walking
派生
派生是在子类继承父类的基础上, 定义子类独有的属性,例如Teacher可以有教师等级的划分、有教学课程的划分,但是继承父类People类是没有等级和课程的划分的。
示例:
#定义父类Peopleclass People: def __init__(self, name, age,sex): self.name = name self.age = age self.sex=sex def walk(self): print('%s is walking' % self.name) def test(self): print('test class from father class %s' %self.name)#定义Teacher子类class Teacher(People): school = 'jialidun' def __init__(self, name, age,sex,level,salary): People.__init__(self,name,age,sex) #继承父类的初始化内容,实例化时候接收的参数name、age、sex会传给People.__init__ self.level=level #派生的独有属性 self.salary=salary #派生的独有属性 def teach(self): #派生的独有属性 print('%s is teaching' %self.name) def test(self): #派生父类的已有属性,对象在进行属性引用的时候会优先引用实例化过程中用到的类 People.test(self) print('from teacher')#定义Student子类class Student(People): def __init__(self, name, age,sex,group): People.__init__(self, name, age, sex) self.group=group def study(self): print('%s is studying' %self.name)
测试验证:
t=Teacher('natasha',18,'male',10,3000)#__init__(t,'natasha',18,'male',10,3000)print(Teacher.__bases__)print(Teacher.__dict__)t.test()
组合
不同于继承,组合是包含的意思,表示一种什么有什么的关系,也是为了减少重复代码的
示例:还是People、Teacher和Student的例子,只是加上了一个Birthday生日类
#Birthday类,需要传入年月日class Birthday: def __init__(self,year,mon,day): self.year=year self.mon=mon self.day=day def tell_birth(self): print('出生于<%s>年 <%s>月 <%s>日' % (self.year,self.mon,self.day))#People类,需要接受名字年龄年月日,年月日传给Birthday类class People: def __init__(self, name, age, year, mon, day): self.name = name self.age = age #__init__接收的year, mon, day传给Birthday类 self.birth = Birthday(year, mon, day) #包含Birthday类,生日不只是人类才有,其他动物也可以有生日,不同于继承 def walk(self): print('%s is walking' % self.name)#Teacher类class Teacher(People): def __init__(self, name, age, year, mon, day,level,salary): #__init__接收的name, age, year, mon, day传给People类 People.__init__(self,name,age,year,mon,day) self.level=level self.salary=salary def teach(self): print('%s is teaching' %self.name)#Student类class Student(People): def __init__(self, name, age, year, mon, day,group): People.__init__(self,name,age,year,mon,day) self.group=group def study(self): print('%s is studying' %self.name)
测试验证:
t=Teacher('hurry',18,1990,2,33,10,3000) #传入的值为Teacher类接收的值print(t.name,t.age) #对象t的名字和年龄print(t.birth) #输出的是一个类对象,因为父类People定义的birth属性就是一个类Birthdayt.birth.tell_birth() #查看对象t所继承的People类的birth属性(Birthday类)的tell_birth()属性print(t.birth.year)print(t.birth.mon)print(t.birth.day)
接口和抽象类
接口
接口是一组功能的入口,要调用某一组功能,需要通过接口来进行调用,而不需要关注这组功能是如何实现的,要的只是结果。
在类里,接口是提取了一群类共同的函数,可以把接口当做一个函数的集合。
python模仿接口示例:
#模仿Linux内文件读写的接口,Linux不管是文本,还是磁盘还是进程都是通过文件去实现的,只不过方法不同,但是没关系class File: #定义一个接口类,提供read和write方法,但是一定是pass没有处理过程的,因为功能的实现具体靠的是子类 def read(self): #定接口函数read pass def write(self): #定义接口函数write pass#定义子类实现读写功能#文本文件的读写class Txt(File): #文本,具体实现read和write def du(self): #注意并不是read print('文本数据的读取方法') def xie(self): #注意并不是write print('文本数据的写入方法')#硬盘数据的读写class Sata(File): #磁盘,具体实现read和write def read(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的写入方法')#进程数据的读写class Process(File): def read(self): print('进程数据的读取方法') def write(self): print('进程数据的写入方法')
测试验证:硬盘和进程一样,所以制作文本和硬盘的测试即可
硬盘读写测试:
disk=Sata() #实例化一个硬盘读写对象disk.read() #硬盘读disk.write() #硬盘写输出结果:硬盘数据的读取方法硬盘数据的写入方法
文本读写测试:执行后会发现没有任何输出,那是因为txt对象实际上访问的read和write属性并非子类Txt所提供的属性,Txt所提供的属性只是du和xie,但是txt对象有read和write属性,别忘了Txt类是继承了父类File的属性,所以实际上txt对象的read和write属性是父类File提供的
txt=Txt()txt.read()txt.write()
正确的做法是将Txt类的du和xie方法改成read和write方法,这么做的意义为归一化
归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。
抽象类
抽象类的本质上也是类,但是抽象类只能够被继承,不能进行实例化,也就是说可以当父类,但是不能生成对象。
抽象类介于接口和归一化中间,用于实现接口的归一化
当子类继承抽象类的时候,如果抽象类定义了抽象方法,那么子类必须要定义同名的方法。即父类限制:
1、子类必须要有父类的方法
2、子类实现的方法必须跟父类的方法的名字一样
python的抽象类通过abc模块实现。
接口归一化示例:
import abcclass File(metaclass=abc.ABCMeta): #metaclass指的是元类,边会讲,现在只需记住这个词 @abc.abstractmethod #抽象方法,即一个装饰器装饰read属性 def read(self): pass @abc.abstractmethod #抽象方法,即一个装饰器装饰write属性 def write(self): pass# # 当继承File类时候,如果没有read和write方法,会提示出错TypeError: Can't instantiate abstract class Txt with abstract methods read, write# class Txt(File):# def du(self):# print('文本数据的读取方法')# def xie(self):# print('文本数据的写入方法')#定义子类具体实现文本的读写操作class Txt(File): def read(self): print('文本数据的读取方法') def write(self): print('文本数据的写入方法')#定义子类具体实现硬盘的读写操作class Sata(File): def read(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的写入方法')#定义子类具体实现进程的读写操作class Process(File): def read(self): print('进程数据的读取方法') def write(self): print('进程数据的写入方法')
测试验证: t=Txt()
t.read()
t.write()
s=Sata()
s.read()
s.write()
输出结果:
文本数据的读取方法
文本数据的写入方法
硬盘数据的读取方法
硬盘数据的写入方法
- DAY31继承派生、组合、接口和抽象类
- 继承和组合、抽象类和接口
- 继承,接口和抽象类
- 继承、抽象类和接口
- 抽象类接口和继承
- 抽象类接口和继承
- 黑马程序员-Java的面向对象(抽象类、接口、内部类和继承、组合、多态)
- C#继承接口的类和派生接口的实现
- C#中的继承 (继承、抽象类和抽象方法、接口)
- C#中的继承 (继承、抽象类和抽象方法、接口)
- 类、抽象类、接口、继承和对象
- 深入继承 - 抽象类和接口
- 深入继承 - 抽象类和接口
- 深入继承 - 抽象类和接口
- 继承之接口和抽象类区别
- 继承之接口和抽象类区别
- 深入继承 - 抽象类和接口
- java继承、接口和抽象类
- 华为上机编程之计算字符串最后一个单词的长度,单词以空格隔开
- 类名.class 类名.this 详解
- C编程(三)流程控制之选择
- 面向对象程序设计
- C++ 运算符 重载
- DAY31继承派生、组合、接口和抽象类
- EA&UML日拱一卒-活动图::CallOperationAction
- java多线程实现服务器端与多客户端之间的通信
- Hash冲突解决——拉链法
- 提高网页加载速度的方法
- Jenkins入门系列之——02第二章 Jenkins安装与配置
- python3 [爬虫入门实战] 爬虫之爬取盘多多文档(百万数据)
- 2017上
- 基于HTML5的五子棋游戏