走入计算机的第二十九天(继承与派生)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了走入计算机的第二十九天(继承与派生)相关的知识,希望对你有一定的参考价值。

一 什么是继承

继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类

  单继承:就相当于子类继承了一个父类。

    多继承:就相当于子类继承了多个父类。

python中类的继承分为:单继承和多继承

 1 class ParentClass1: #定义父类
 2     pass
 3 
 4 class ParentClass2: #定义父类
 5     pass
 6 
 7 class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
 8     pass
 9 
10 class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
11     pass

查看继承

查看类继承了哪个父类的方式:子类名.__bases__

>>> SubClass1.__bases__ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
(<class ‘__main__.ParentClass1‘>,)
>>> SubClass2.__bases__
(<class ‘__main__.ParentClass1‘>, <class ‘__main__.ParentClass2‘>)

 提示:如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。

1 >>> ParentClass1.__bases__
2 (<class object>,)
3 >>> ParentClass2.__bases__
4 (<class object>,)
在python3中,所有类默认继承object(在python3当中所有类都是新式类)
但凡是继承了object类的子类以及该子类的子类,都称为新式类
没有继承object类的子类成为经典类(在python2 中,没有继承object类,以及它的子类,都是经典类。)

继承与抽象(先抽象再继承)

抽象即抽取类似或者说比较像的部分。

解决代码重用的问题,减少代码冗余
继承是一种什么‘是’什么的关系
抽象分成两个层次: 

1.将奥巴马和梅西这俩对象比较像的部分抽取成类; 


2.将人,猪,狗这三个类比较像的部分抽取成父类。


抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)


技术分享 


继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。


抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类


技术分享
三  组合与重用性

软件重用的重要方式除了继承之外还有另外一种方式,即:组合

组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

组合:什么有什么的关系,也是为了减少重复代码

其实早在3.5小节中我们就体会了组合的用法,比如一个英雄有一个装备

 1 >>> class Equip: #武器装备类
 2 ...     def fire(self):
 3 ...         print(release Fire skill)
 4 ... 
 5 >>> class Riven: #英雄Riven的类,一个英雄需要有装备,因而需要组合Equip类
 6 ...     camp=Noxus
 7 ...     def __init__(self,nickname):
 8 ...         self.nickname=nickname
 9 ...         self.equip=Equip() #用Equip类产生一个装备,赋值给实例的equip属性
10 ... 
11 >>> r1=Riven(锐雯雯)
12 >>> r1.equip.fire() #可以使用组合的类产生的对象所持有的方法
13 release Fire skill

组合与继承都是有效地利用已有类的资源的重要方式。但是二者的概念和使用场景皆不同,

1.继承的方式

通过继承建立了派生类与基类之间的关系,它是一种‘是‘的关系,比如白马是马,人是动物。

当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如教授是老师

 1 >>> class Teacher:
 2 ...     def __init__(self,name,gender):
 3 ...         self.name=name
 4 ...         self.gender=gender
 5 ...     def teach(self):
 6 ...         print(teaching)
 7 ... 
 8 >>> 
 9 >>> class Professor(Teacher):
10 ...     pass
11 ... 
12 >>> p1=Professor(egon,male)
13 >>> p1.teach()
14 teaching

用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python课程

技术分享
 1 class People:
 2 #     def __init__(self,name,age,year,mon,day):
 3 #         self.name=name
 4 #         self.age=age
 5 #         self.birth=Date(year,mon,day)
 6 #     def walk(self):
 7 #         print(‘%s is walking‘ %self.name)
 8 # class Date:
 9 #     def __init__(self,year,mon,day):
10 #         self.year=year
11 #         self.mon=mon
12 #         self.day=day
13 #     def tell_birth(self):
14 #         print("出生于<%s>年 <%s>月 <%s>日"%(self.year,self.mon,self.day))
15 #
16 # class Student(People):
17 #     def __init__(self,name,age,year,mon,day,group):
18 #         People.__init__(self,name,age,year,mon,day)
19 #         self.group=group
20 #     def study(self):
21 #         print(‘%s is studying‘ %self.name)
22 #
23 # class Teacher(People):
24 #     def __init__(self,name,age,year,mon,day,level,salary):
25 #         People.__init__(self,name,age,year,mon,day)
26 #         self.level=level
27 #         self.salsry=salary
28 #     def teach(self):
29 #         print(‘%s is teaching‘ %self.name)
30 #
31 # t=Teacher(‘egon‘,18,1990,2,33)
32 # print(t.name,t.age)
33 # print(t.birth)
34 # print(t.birth.year)
35 # print(t.birth.mon)
36 # print(t.birth.day)
37 #
38 #
39 #
40 # t=Student(‘fang‘,18,1990,2,25)
41 # print(t.name,t.age)
42 # print(t.birth)
43 # print(t.birth.year)
44 # print(t.birth.mon)
45 # print(t.birth.day)
View Code

当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好

四   接口与归一化设计

什么是接口?接口只是定义了一些方法,而没有去实现,多用于程序设计时,只是设计需要有什么样的功能,但是并没有实现任何功能,这些功能需要被另一个类(B)继承后,由 类B去实现其中的某个功能或全部功能。,

继承有两种用途:

     1 继承基类的方法,并且做出自己的改变或者扩展(代码重用)

     2 声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能

技术分享
 1 # class Interface:   #定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字
 2 #     def read(self):     #定接口函数read
 3 #         pass
 4 #     def write(self):    #定接口函数write
 5 #         pass
 6 # class Txt(Interface):   #文本,具体实现read和write
 7 #     def read(self):
 8 #         print(‘文本数据的读取方法‘)
 9 #     def write(self):
10 #         print(‘文本数据的写入方法‘)
11 # class Sata(Interface):      #硬盘,具体实现read和write
12 #     def read(self):
13 #         print(‘硬盘数据的读取方法‘)
14 #     def write(self):
15 #         print(‘硬盘数据的写入方法‘)
16 # class Process(Interface):
17 #     def read(self):
18 #         print(‘进程数据的读取方法‘)
19 #     def write(self):
20 #         print(‘进程数据的写入方法‘)
21 #
22 #
23 # txt=Txt()
24 # disk=Sata()
25 # process=Process()
26 #
27 #
28 # txt.read()
29 # disk.read()
30 # process.read()
View Code

实践中,继承的第一种含义意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。

继承的第二种含义非常重要。它又叫“接口继承”。
接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。

归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。

 

在python中根本就没有一个叫做interface的关键字,上面的代码只是看起来像接口,其实并没有起到接口的作用,子类完全可以不用去实现接口 ,如果非要去模仿接口的概念,可以借助第三方模块:

为何要用接口

接口提取了一群类共同的函数,可以把接口当做一个函数的集合。

然后让子类去实现接口中的函数。

这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。

归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。

比如:我们定义一个动物接口,接口里定义了有跑、吃、呼吸等接口函数,这样老鼠的类去实现了该接口,松鼠的类也去实现了该接口,由二者分别产生一只老鼠和一只松鼠送到你面前,即便是你分别不到底哪只是什么鼠你肯定知道他俩都会跑,都会吃,都能呼吸。

再比如:我们有一个汽车接口,里面定义了汽车所有的功能,然后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,大家只需要学会了怎么开汽车,那么无论是本田,还是奥迪,还是大众我们都会开了,开的时候根本无需关心我开的是哪一类车,操作手法(函数调用)都一样












以上是关于走入计算机的第二十九天(继承与派生)的主要内容,如果未能解决你的问题,请参考以下文章

走入计算机的第二十六天(内置模块4)

走入计算机的第二十八天(面向对象的程序设计)

走入计算机的第二十五天(内置模块3之正则表达式)

走入计算机的第四十九天(JavaScript语言二)

走入计算机的第三十九天(python终结篇之IO模型)

学习python课程第二十二天