关于类继承资源的覆盖
(1)体现:覆盖和重写
(2)原理:根据MRO链的优先级,对类中的资源进行调用时,会优先调用优先级高的类中的资源,这样,如果优先级低的类中也有同样的资源,则不会被调用,这就相当于是被覆盖了;重写也是同样的道理,重写后的资源会被优先调用,覆盖掉优先级低的类中的相同资源
(3)注意调用资源时self和cls的变化:使用的是谁实例化出来的对象,或使用的是哪那个类,self就是哪个实例,cls就是哪个类
关于类继承资源的累加
(1)概念:在一个父类的基础上,增加一个子类自己特有的资源
(2)场景:1.子类与父类相比,多一些属于自己的资源;2.在被覆盖的方法基础之上,新增功能
(3)场景1代码实现:
class A(object): a = 10 def __init__(self): self.aa = 1 def a3(self): print("a3") @classmethod def a1(cls): print("a1") @staticmethod def a2(): print("a2") class B(A): b = 9 def b3(self): print("b3") @classmethod def b1(cls): print("b1") @staticmethod def b2(): print("b2")
(4)场景2有两种实现方法,第一种是在B类中重写A中方法,并在加入新功能后对A中的方法进行调用,代码如下:
class A(object): a = 10 def aa(self): print("aa") class B(A): def bb(self): print("bb") A.aa(self) b = B() b.bb()
这里aa()是A类的实例方法,但是在B类中对其进行调用时,不能使用A类的实例对象进行调用,因为这里是给B的实例方法新增内容,如果使用A类的实例对象进行调用,则不会将内容增加到B的实例方法中,代码A.aa(self)中的self是bb()方法传进来 ,所以是B的实例对象;这里使用的方式其实也存在弊端,那就是如果父类的类名被改变,那么在子类中调用父类方法时,前面的父类类名就要跟着改变,这样的代码就很不好了
方式二:在低优先级的类中通过super来调用高优先级的类方法(重点)。
super概念:super是一个类,且只有在新式类中才有效
super作用:代理作用,它沿着MRO链寻找下一级节点,并调用对应的方法。这里需要注意的是,在MRO链中属于上下级关系的不一定是继承关系,例如有重叠多继承形态的MRO链
super中需要解决的问题:1.找谁的下一个节点;2沿着谁的MRO链条.;3.参数如何传递
super的语法原理:
super的常用语法形式:
使用super对方法进行新增内容,代码如下:
class A(object): a = 10 def aa(self): print("aa") self.a1 = 19 class B(A): def bb(self): print("bb") self.b1 = 20 super(B, self).aa() b = B() b.bb()
填super中的两个参数时要考虑两个问题,首先,是在找谁的下一个节点,这里是找A,而A是B的下一个节点,所以第一个参数填B类;然后是沿着谁的MRO链条寻找,有前面语法原理知,是要找一条MRO链条,并找到B类在该链条中的索引位置,然后加1,就可以找到下一个节点的索引位置,那么,要找的这条MRO链条一定要包含有B类,所以,第二个参数可以填B类和其实例或者B类的子类和其实例。第二个参数的作用除了寻找MRO链条,还决定了向A类方法中传第的参数,所以这里如果需要传递类,则第二个参数填类,需要传递实例,则第二个参数填实例。上述代码中aa(self)方法是实例方法,需要传递实例,所以super的第二个参数直接填self即可,这里的self表示B类的实例