继承
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
<strong>继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。</strong>
python中类的继承分为:单继承和多继承
<span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">一个类 可以被多个类继承,<span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">一个类 可以继承多个父类</span> </span>
<strong><font color="#000080">python3中,都是新式类,</font></strong><span style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">没有继承父类默认继承 object</span>
先抽象再继承
抽象即抽取类似或者说比较像的部分。
抽象最主要的作用是划分类别
抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类
用已经有的类建立一个新的类,这样就重用了已经有的软件中的一部分设置大部分,大大省了编程工作量,这就是常说的软件重用,不仅可以重用自己的类,也可以继承别人的,比如标准库,<p>来定制新的数据类型,这样就是大大缩短了软件开发周期,对大型软件开发来说,意义重大.</p>
派生
<strong>子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。</strong>
<p><strong>通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。</strong></p><p><strong>当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如教授是老师</strong></p>
抽象类与接口类
接口类
继承有两种用途
一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能
例子
抽象类
<strong>抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化</strong>
<p>抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。</p><p><strong>抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计 </strong></p>
<span style="font-size: 1em;">在抽象类中,我们可以对一些抽象方法做出基础实现;<br>而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现</span>
<span style="color: rgb(0, 0, 0);">接口隔离原则:<br>使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。</span>
方法的实现
<span style="font-size: 1em;">在抽象类中,我们可以对一些抽象方法做出基础实现;<br>而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现</span>
钻石继承
继承顺序
当类是经典类时,多继承情况下,会按照深度优先方式查找
当类是新式类时,多继承情况下,会按照广度优先方式查找
名词解析
<span style="color: rgb(0, 0, 0);">抽象:抽象即抽取类似或者说比较像的部分。是一个从具题到抽象的过程。<br></span>
继承:子类继承了父类的方法和属性<br>
派生:子类在父类方法和属性的基础上产生了新的方法和属性
小结
多态
多态指的是一类事物有多种形态。Python3天生支持多态。
鸭子类型
封装
隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处
1. 将变化隔离
2. 便于使用
3. 提高复用性
4. 提高安全性
封装原则
将不需要对外提供的内容都隐藏起来
把属性都隐藏,提供公共方法对其访问
<strong>私有变量和私有方法</strong>
<strong>在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)</strong>
<p><strong>这种自动变形的特点:</strong></p><p><strong>1.类中定义的</strong><strong>__x只能在内部使用,如self.__x,<strong><strong>引用的就是变形的结果</strong></strong>。</strong></p><p><strong><strong>2.这种变形其实正是针对外部的变形</strong><strong>,在外部是无法通过__x这个名字访问到的。</strong></strong></p><p><strong>3.在子类定义的__x不会覆盖在<strong>父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。</strong></strong></p>
这种变形需要注意的问题
<strong>这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N</strong>
<strong>变形的过程只在类的内部生效,在定义后的赋值操作,不会变形</strong>
<span data-key="285">私有方法</span>
<strong>在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的</strong>
<strong>封装与扩展性</strong>
<strong>封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。</strong>