zoukankan      html  css  js  c++  java
  • 面向对象之集成

    继承

    什么是继承

    继承是一种关系,描述两个对象之间,什么是什么的关系

    例如麦兜,佩奇,猪刚鬣 都是猪啊,

    在程序中,继承描述的是类和类之间的关系

    例如a继承了b, a就能直接使用b已经存在的方法和属性

    a称之为子类,b称之为父类,也称之为基类

    class Base:
        desc = "这是一个基类"
        def show_info(self):
            print(self.desc)
        def make_money(self):
            print("一天赚一个亿...")
    #指定父类位Base
    class SubClass(Base):
        pass
    obj = SubClass()
    #即使类中什么都没有也可以使用父类中已有的内容
    obj.make_money()
    print(obj.desc)
    

    为什么要使用继承:

    继承的一方可以直接使用被继承一方已经有的东西

    其目的是为了重用已经有的代码,提高重用性

    如何使用继承

    语法:

    class 类名称(父类的名称):
        类的内容 
        
    #在python中 一个子类可以同时继承多个父类 
    
    
    class Person:
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def say_hi(self):
            print("name:%s,gender:%s,age:%s" % (self.name,self.gender,self.age))
    
    
    class Teacher():
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
            print("老师教学生,写代码....")
        def say_hi(self):
            print("name:%s,gender:%s,age:%s" % (self.name,self.gender,self.age))
    
    t1 = Teacher("jack","male",20)
    t1.say_hi()
    

    补充:

    两个类中的内容完全一致,则可以通过继承来重用代码

    class Teacher:
        def __init__(self,name,gender,age):
            self.name = name
            self.gender = gender
            self.age = age
        def say_hi(self):
            print("hi my name is %s age is %s gender is %s" % (self.name,self.age,self.gender))
    
    class Student(Teacher):  #指定Teacher类继承Student类
        pass
    
    #创建两个对象
    t1 = Teacher("Jack","man",20)
    t1.say_hi()
    s1 = Student("Maria","woman",20)
    s1.say_hi()
    

    抽象:

    不具体,不清晰,很模糊,看不懂

    将多个子类中相同的部分,进行抽取,形成一个新的类,这个过程也称之为抽象的过程

    正确的使用继承:

    1.先抽象在继承 
    
    2.继承一个已经现存的类,扩展或是修改原始的功能 
    
    # 抽取老师和学生中相同的部分形成person类
    class Person:
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
        def say_hi(self):
            print("name:%s,gender:%s,age:%s" % (self.name,self.gender,self.age))
    class Teacher(Person):
        def teaching(self):
            print("老师教学生,写代码....")
    t1 = Teacher("jack","male",20)
    t1.say_hi()
    class Student(Person):
        pass
    stu1 = Student("rose","female",18)
    stu1.say_hi()
    list
    

    属性的查找顺序

    class A:
        text = "haha"
    
    class B(A):
        text = "heihei"
        pass
    
    b = B()
    b.text = "xixi"
    
    print(b.text)
    

    对象自己的 - > 所在类中 -> 找父类 - >父类的父类 ->Object

    派生

    当一个子类中出现了与父类中不同的内容时,这个子类就称之为派生类

    通常子类都会写一些新的代码,不可能和父类完全一样 , 既通常都是派生类,

    所以派生类指的就是子类

    覆盖

    也称之为重写 overrides

    当子类出现了与父类名称完全一致的属性或是方法

    class Person:
        def say_hi(self):
            print("hello")
    
    class Student(Person):
        def say_hi(self):
            print("hello world!")
    stu = Student()
    stu.say_hi()
    
    
    练习:

    实现一个可以限制元素类型的容器 (字典,列表,元组,集合,字符串)

    1.list:现成的“类”

    class MyList(list):
        pass
    m=MyList()
    m.append(2)
    print(m[0])
    #2
    

    2.代码

    class MyList(list):
        def __init__(self,element_type):#当有需求在创建对象时,干点什么事,就想到初始化方法。
            self.element_type=element_type
        def append(self,object):
            if type(object)==self.element_type:#此处限制类型
                super().append(object)#在子类中访问父类list的元素
            else:
                print('sorry sir your element isnt %s'%self.element_type)
    
    m=MyList(int)#此处指定类型
    m.append(2)
    
    print(m[0])
    m.append('1')
    print(m[0])
    

    子类中访问父类的内容

    语法:

    方式1:
    super(当前类名称,self).你要调的父类的属性或方法
    方式2:
    super().你要调的父类的属性或方法
    方式3:
    类名称.你要调的父类的属性或方法(self)  
    #方式3与继承无关 
    

    强调在强调:

    当你继承一个现有的类,并且你覆盖了父类的init方法时,必须在初始化方法的第一行调用父类的初始化方法,并传入父类所需的参数

    # class Person:
    #     def __init__(self,name,gender,age):
    #         self.name = name
    #         self.gender = gender
    #         self.age = age#
    #     def say_hi(self):
    #         print("name:%s ,gender:%s,age:%s" % (self.name,self.gender,self.age))
    #
    # class Student(Person):
    #     def __init__(self,name,gender,age,number):
    #         super().__init__(name, gender, age)
    #         self.number= number
    #
    #     def say_hi(self):
    #         super().say_hi()
    #         print("numnber:%s" % self.number)
    #
    # stu = Student("rose","mael",20,"old01")
    # stu.say_hi()
    
    # 为什么要在初始化方法中调用 父类的初始化方法
    class Person:
        def __init__(self,name,gender,age,*args):
            self.name = name
            self.gender = gender
            self.age = age
            self.aa()
    
        def aa(self):
            print("aa run")
    
        def say_hi(self):
            print("name:%s ,gender:%s,age:%s" % (self.name,self.gender,self.age))
    
    class Student(Person):
        def __init__(self,name,gender,age,number)
            super().__init__(name,gender,age)#如果不引用父类的初始化方法,那么,下面调用父类对象中的内容则被覆盖无法引用
            self.number= number
    
        def say_hi(self):
            super().say_hi()
            print("numnber:%s" % self.number)
    
    stu = Student("rose","mael",20,"old01")
    stu.say_hi()
    
    

    组合

    也是一种关系,描述两个对象之间 是什么有什么的关系

    例如,学生有手机 ,游戏中角色拥有某些装备

    将一个对象作为另一个对象的属性,(既什么有什么)

    组合的目的:

    也是为了重用现有代码

    什么时候使用继承:分析两个类的关系,到底是不是:什么是什么的关系

    什么时候使用组合:如果两个类之间 没有太大的关系,完全不属于同类

    另外组合相比继承,耦合度更低了

    class Phone:
        def __init__(self,price,kind,color):
            self.price = price
            self.kind = kind
            self.color = color
    
        def call(self):
            print("正在呼叫XXXX;")
    
        def send_message(self):
            print("正在发送短信....")
    
    
    class Student:
        def __init__(self,name,gender,phone):
            self.name = name
            self.gender = gender
            self.phone = phone
    
        def show_info(self):
            print("name:%s gender:%s" % (self.name,self.gender))
    
    phone = Phone(1000,"apple","red")
    stu1 = Student("rose","male",phone)
    stu1.phone.call()
    

    了解知识点

    菱形继承

    首先明确python支持多继承

    
    # 菱形继承
    # class A:
    #     j = 1
    #     pass
    #
    # class B:
    #     # j = 2
    #     pass
    #
    # class C(A):
    #     # j = 3
    #     pass
    #
    # class D(A):
    #     j = 4
    #     pass
    #
    # class E(B,C,D):
    #     # j = 5
    #     pass
    #
    # d = E()
    # print(d.j)
    
    class B:
        # num = 2
        pass
    
    class C:
        # num = 3
        pass
    
    
    class E(B):
        # num = 5
        pass
    
    class F(C):
        # num = 6
        pass
    
    class G(C):
        num = 7
        pass
    
    class H(E,F,G):
        # num = 8
        pass
    
    print(H.num)
    # print(H.mro())
    
    #[H,E,B,F,G,C,object]
    
    
    补充:新式类与经典类

    python3中任何类都是直接或间接继承了Object

    新式类,任何显式或隐式地继承自object的类就称之为新式类, python3中全都是新式类

    经典类,既不是Object的子类 ,仅在python2中出现

    当出现了菱形继承时,新式类,先深度,当遇到了共同父类时就广度

    								新式类,就是深度优先
    

    小结:

    1.继承是什么

    2.为什么用继承

    3.语法

    4.先抽象在继承

    6.派生

    7.覆盖

    8.子类访问父类的属性或方法 super ().名字

    如果你继承一个已有的类,并且你覆盖了init  一定要先调用父类的init 
    

    9.继承的原理,mro列表

    10,新式类与经典类

    11.菱形继承 了解

    12,属性的查找顺序

  • 相关阅读:
    pycharm运行程序,总是出现IPthony界面(IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help. PyDev console: using IPython 6.2.1)
    《剑指offer》第十一题:旋转数组的最小数字
    《剑指offer》第十题:斐波那契数列
    《剑指offer》第九题:用两个栈实现队列
    《剑指offer》第八题:二叉树的下一个节点
    《剑指offer》第七题:重建二叉树
    《剑指offer》第六题:从尾到头打印链表
    《剑指offer》第五题:替换空格
    《剑指offer》第四题:二维数组中的查找
    《剑指offer》第三题II:不修改数组找出重复的数字
  • 原文地址:https://www.cnblogs.com/ZDQ1/p/11248078.html
Copyright © 2011-2022 走看看