美文网首页
(八)方法的继承、重写和扩展

(八)方法的继承、重写和扩展

作者: 小雨Coding | 来源:发表于2020-08-25 22:19 被阅读0次

    一、继承

    1.封装与继承的概念

    封装:根据需求将属性和方法封装到一个抽象的类中;
    继承:获得父类的属性和方法,实现代码的复用

    2.继承的语法:
    class 类名(父类名)
        具体的代码
    

    案例:

    class A:
        def __init__(self):
            self.name = "alice"
            self.age = "24"
        def show(self):
            print("====A=====")
            
    class B(A):
        pass
    
    3. 常用术语

    第一种:父类、子类、继承
    A类是B类的父类,B类是A类的子类,B类由A类继承而来;
    第二种:基类、派生类、派生
    A类是B类的基类,B类是A类的派生类,B类由A类派生而来;

    4. 继承的案例

    在前面GUI的开发过程中,实际上我们也可以使用继承的思想来开发。定义一个基类绘制基础的窗体框架,然后再定义若干派生类来派生基类,这样就能减少大量的重复工作。

    from tkinter import *
    from tkinter.ttk import *
    
    # 创建GUI基类
    class GUIBase:
        def __init__(self,title):
            self.frame = Tk()
            self.frame.title(title)
            self.frame.geometry("610x500+600+150")
            self.frame.resizable(0,0)
            self.frame["bg"] = "lightgray"
            # 配置Style
            self.frame.Style01 = Style()
            self.frame.Style01.configure("TPanedwindow",background = "whitesmoke")
            self.frame.Style01.configure("TButton",font=("微软雅黑",16,"bold"))
            self.frame.Style01.configure("TLabel", font=("微软雅黑", 20, "bold"))
            # 添加顶部的banner
            self.top_banner_image = PhotoImage(file = "./img/stu_detail_banner.png")
            self.frame.top_banner = Label(image = self.top_banner_image)
            self.frame.top_banner.place(x=5,y=5)
            # 添加一个Label标签
            self.Label01 = Label(self.frame,text = title)
            self.Label01.place(x=20,y=20)
            # 加载一个Pane容器
            self.frame.Pane_detail = PanedWindow(self.frame,width = 600,height = 370)
            self.frame.Pane_detail.place(x=5,y=95)
            # 添加最下面的关闭按钮
            self.frame.Button_close = Button(self.frame,text = "关闭",width = 10,command = self.close)
            self.frame.Button_close.place(x=470,y=470)
    
        def close(self):
            self.frame.destroy()
    
        def show(self):
            self.frame.mainloop()
    
    # 派生出两个GUI派生类
    class GUI01(GUIBase):
        def __init__(self,title):
            GUIBase.__init__(self,title)
    
            self.frame.Button_GUI01 = Button(self.frame,text = "GUI01",width = 10)
            self.frame.Button_GUI01.place(x=20,y=100)
    
    class GUI02(GUIBase):
        def __init__(self,title):
            GUIBase.__init__(self,title)
    
            self.frame.Button_GUI02 = Button(self.frame,text = "GUI02",width = 10)
            self.frame.Button_GUI02.place(x=20,y=200)
    
    if __name__ == '__main__':
        this = GUI02("添加学生信息")
        this.show()
    

    我们定义了一个基类GUIBase和两个派生类GUI01GUI02,在派生类中添加按钮,这样在通过派生类的构造方法构造对象时会自动具备基类的属性。
    同样,基类的构造方法也是可以传递参数给派生类的,这里我们就定义了一个参数title这样我们就每次通过派生类实例化对象时传递参数title,基类的title变量就会自动获取值。

    5. 继承的传递性

    子类会继承父类的属性和方法,并且具有传递性。父类的父类的方法也会传递下来,每一次继承的时候可以添加属性,子类继承当前类的时候会自动具备该属性。

    # 父类
    class Person:
        def __init__(self,name):
            self.name = name
        def walk(self):
            print("可以走路")
    
    # 由Person类继承出Chinese类
    class Chinese(Person):
        def __init__(self,name,id):
            Person.__init__(self,name)
            self.id = id
        def say(self):
            print("会说汉语")
    
    # 由Chinese继承出ChineseStudent类
    class ChineseStudent(Chinese):
        def __init__(self,name,id,sno):
            Chinese.__init__(self,name,id)
            self.sno = sno
        def study(self):
            print("准备高考")
    
    if __name__ == '__main__':
        swift = ChineseStudent("张三","342612199810236832","3140705135")
        swift.walk()
        swift.say()
        print(swift.id)
        print(swift.sno)
    

    我们定义一个父类Person类,具备属性:名字,具备方法:可以走路;定义一个子类Chinese继承Person类,添加属性:身份证号,添加方法:会说汉语;再定义一个子类ChineseStudent继承Chinese类,添加属性:学号,添加方法:学习;这样我们通过ChineseStudent类构造的对象具备Chinese的属性和方法,同样也具备Person类的属性和方法。
    运行结果:

    可以走路
    会说汉语
    342612199810236832
    3140705134
    
    6. object类

    Python中查看一个类的基类可以使用类名.__base__查看,常见的intlist其实也是一个类,我们可以查看其基类

    # 查询一个类的基类
    print(int.__base__)
    print(list.__base__)
    

    输出结果

    <class 'object'>
    <class 'object'>
    

    我们发现它们的基类都指向了同一个类,那就是object类,object类是什么呢?
    object类是Python中所有类的基类;
    如何查看一个类中有哪些方法呢?
    使用dir(类名)即可查看一个类中所具备的所有方法

    print(dir(object))  # 查看object类中所具备的所有方法
    

    运行结果:

    ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
    
    7. 新式类和经典类

    只有在Python2.x的版本中,才有这个特性,
    旧式类创建方法:class Person:
    新式类的创建方法:class Person(object)
    在Python 3.x版本中,如果不指明父类,默认父类就是object

    二、方法的重写和扩展

    1. 组合和继承

    继承:自动获得父类所有的属性和方法
    组合:需要手工拼接,访问的时候需要多层次的访问

    class Person:
        def __init__(self,name):
            self.name = name
        def walk(self):
            print("走路")
    
    class Chinese:
        def __init__(self,Person:Person,chinese_id):
            self.Person = Person
            self.chinese_id = chinese_id
        def speak_chinese(self):
            print("大家好,很高兴认识你!")
    
    # ==== 使用 =======
    if __name__ == '__main__':
    
        cool_boy = Person("张三")
        zhangsan = Chinese(cool_boy,"342612199710127863")
        # 使用两种方法访问Person01中的方法
        zhangsan.Person.walk()
        cool_boy.walk()
        # 使用两种方法访问Person01中的属性
        print(zhangsan.Person.name)
        print(cool_boy.name)
    
    2.方法的重写

    在继承的过程中,如果继承来的方法不符合实际的引用,需要对方法进行重写。
    重写规则:方法名称一样
    某一个实例在访问某一个方法,父类中有这个方法,但父类的父类也有这个方法,然而实际上系统会调用父类中的方法。

    # 基类
    class Person:
        def __init__(self,name):
            self.name = name
        def eat(self):
            print("吃饭")
    
    # 由Person类派生出Chinese类
    class Chinese(Person):
        def __init__(self,name,id):
            Person.__init__(self,name)
            self.id = id
    
        def say(self):
            print("会说汉语")
    
        # 重写eat方法
        def eat(self):
            print("我是中国人,我爱吃米饭")
    
    # 由Chinese派生出ChineseStudent类
    class ChineseStudent(Chinese):
        def __init__(self,name,id,sno):
            Chinese.__init__(self,name,id)
            self.sno = sno
        def study(self):
            print("正在学习中国近代史")
    
    if __name__ == '__main__':
        alice = ChineseStudent("李四","342356199012308789","3140989123")
        alice.eat()
    

    运行结果:

    我是中国人,我爱吃米饭
    

    这里Person类定义了eat()方法,其子类Chinese重写了eat()方法。运行结果表明,当Chinese的子类ChineseStudent这个类实例化的对象alice调用eat()方法时,会以父类Chinese为准。

    3.方法的扩展

    方法的重写使用的场景是:继承来的方法不符合我的实际应用场景;
    方法的扩展使用的场景是:基类的方法符合我的应用,但是不完整,需要进行扩展。
    扩展的原则:在子类中先重新方法,在重写的方法中使用父类名.方法名调用父类的方法,然后进行扩展。

    # 父类
    class Person:
        def __init__(self,name):
            self.name = name
        def eat(self):
            print("吃饭")
    
    # 子类
    class Chinese(Person):
        def __init__(self,name,id):
            Person.__init__(self,name)
            self.id = id
    
        # 扩展eat方法
        def eat(self):
            # 先执行父类中的eat方法
            Person.eat(self)
            # 再扩展自己的eat方法
            print("喜欢吃蛋炒饭")
    if __name__ == '__main__':
        zhansan = Chinese("张三","342712199810126787")
        zhansan.eat()
    

    运行结果

    吃饭
    喜欢吃蛋炒饭
    

    案例中,子类扩展了父类中的eat方法,在扩展父类eat方法时,先通过父类名.方法名调用父类方法,添加自己的扩展方法。这样构造的实例在调用方法时会具备扩展的功能。
    实际上还可以使用super关键字来进行方法的扩展,这时就不用使用self关键字了

    # 父类
    class Person:
        def __init__(self,name):
            self.name = name
        def eat(self):
            print("吃饭")
    
    # 子类
    class Chinese(Person):
        def __init__(self,name,id):
            super().__init__(name)
            self.id = id
    
        # 扩展eat方法
        def eat(self):
            # 使用super关键字扩展
            super().eat()
            # 扩展方法
            print("喜欢吃蛋炒饭")
    if __name__ == '__main__':
        zhansan = Chinese("张三","342712199810126787")
        zhansan.eat()
    

    super()就是一种指针指向父类,有了它调用父类方法,就不用再使用self关键字了。

    相关文章

      网友评论

          本文标题:(八)方法的继承、重写和扩展

          本文链接:https://www.haomeiwen.com/subject/olnijktx.html