面向对象,特性之继承

 

继承父类中对象和方法的语法

class Parent:
  year = 2018
  def coding(self):
      print('coding')
   
class Sub(Parent):
  pass
print(Sub.year)
s1 = Sub()
s1.coding()
4,继承对编程的作用
假设有个学生管理需求:

class Student:
  def __init__(self,name,age,sex):
      self.name = name
      self.age = age
      self.sex = sex
  def study(self):
      print('正在学习中')
  def eat(self):
      print('正在吃饭中')
 

后续又要求添加老师管理需求:

学生的属性和技能也适用于老师,此时可以引用继承,减少代码的冗余

class Teacher(Student):
  pass
t1 = Teacher('alex',30,'man')
t1.eat()
t1.study()

从逻辑上来说,如果学生有打游戏的技能,而老师并没有这个需求,因此继承到了老师并不需要的技能

 

正确姿势: 抽取公共的父类 (抽象)

抽象 : 抽取多个类中相同得部分,形成另一个类

把学生和老师共有的内容抽到另一个类中,学生和老师分别继承这个类,这样就避免了一个类继承到不需要的内容 因此应该先抽象,再继承

 

 

小结:
  • 通过继承,避免了重复代码的编写。

  • 继承的作用是可以直接使用父类已有的代码

  • 通过抽象,避免了一个类继承到不需要的内容

  • 抽象的作用是存储多个子类相同的属性和技能

  • 正确地顺序应该先抽象,再继承

 

 

派生和覆盖

1,派生

class Person:
•  def __init__(self,name,age,sex):
•      self.name = name
•      self.age = age
•      self.sex = sex
​
•  def sayhi(self):
•      print('hello,')
​
class Student(Person):                     # 学生属于人类,可以直接继承def __init__(self,number):             # 加上一些学生特有的属性
•      self.number = number
​
•  def study(self):
•      print('%s正在学习'%self.name)
  • 派生指某个子类继承父类,并且拥有自己独特的属性或技能

  • 该子类称之为派生类

  • 只要子类中出现任何新内容,这就是一个派生类

 

2,覆盖

class A:
  age = 18#age相同
  def f1(self):#f1相同
      print(" A f1" )
  passclass B(A):
  age1 = 19
  def f1(self):#f1
      self.f1()
      print(" B f1")
​
b1 = B()
print(b1.age)
​
b1.f1()
小结:
  • 子类出现了与父类重复的名字 称之为覆盖

  • 子类出现了与父类不同的名字 称之为派生

 

 

子类访问父类的方法

(1) 深度优先,沿着一条线找到底

继承的父类,存在父类,则先把父类找完 ​ 这种查找方式仅仅在非菱形继承(没有共同父类)的情况下

(2 广度优先,并非绝对的广度优先,而是基于深度的广度优先。

先是深度优先,如果发现有共同父类,则返回。最后再查找共同父类 ​

 

 
多重继承的菱形访问

 

class A:
    def ping(self):
        print('ping A:', self)


class B(A):
    def pong(self):
        print('pong B:', self)


class C(A):
    def pong(self):
        print('PONG C:', self)


class D(B, C):
    def ping(self):
        super().ping()
        print('post-ping D:', self)

    def pingpong(self):
        self.ping()
        super().ping()
        self.pong()
        super().pong()
        C.pong(self)
D().ping()
D().pingpong()

mro

method resolution order

MRO步骤:

  1. 按照深度优先,从左到右的顺序

  2. 移除列表中的重复类型,仅保留最后一个

  3. 确保子类总在基类前面,并保留多继承定义顺序

对 bases 的调整会直接影响 mro 的顺序

查看访问路径

"super访问父类内容时 按照mro列表属性查找"

class S:
    def f1(self):
        print("s f1")

class A(S):
    pass

class B(S):
    def f1(self):
        print("b f1")
    pass

class C(A,B):
    def f2(self):
        print("c f2")
        super().f1()


print(C.mro())
c1 = C()
c1.f2()

Tkinter GUI 类层次结构的 UML 简图

 


组合

  • 多个对象放在一起就是组合

  • 一个对象将另一个对象作为自己的属性,就是组合 

 
class Phone:#组合的代码
  def __init__(self,phonenumber,operator,address):
      self.phonenumber = phonenumber
      self.operator = operator
      self.address = address
​
  def call(self,t):
      print("%s 正在拨号 %s" % (t.name,self.phonenumber))
​

class Person:#父类
  def __init__(self,name,sex,age):
      self.name = name
      self.sex = sex
      self.age = age
       
class Student(Person):#子类
  def __init__(self,name,sex,age,number):
      super().__init__(name, sex, age)
      self.number = number
  def show_info(self):
      print(self.__dict__)
  def select_cursor(self):
      print("%s 正在选课...." % self.name)
       
class Teacher(Person):#子类
  def __init__(self,name,sex,age,salary,level):
      super().__init__(name,sex,age)
      self.salary = salary
      self.level = level
  def set_score(self):
      print("%s 正在为学生打分..." % self.name)
​
stu = Student("乔峰","",38,"007")
​
p1 = Phone("1999999999","中国小米移动","上海浦东")
​
stu.q = p1             #这里的q是变量名,相当于把p1赋值给q,通过stu来调用
​
stu.q.call(stu) #不能直接stu.p1.call()
 

 

 

 

 

原文地址:https://www.cnblogs.com/wang-kai-1994/p/10167198.html