zoukankan      html  css  js  c++  java
  • Python 面向对象 --- 多态

    目标

    • 多态

    面向对象三大特性

    1,封装 根据 职责属性方法 封装 到一个抽象的

    • 定义类的准则

    2,继承 实现代码的重用,相同的代码不需要重复的编写

    • 设计类的技巧
    • 子类针对自己特有的需求,编写特定的代码

    3,多态 不同的 子类对象 调用相同的 父类方法,产生不同的执行结果

    • 多态 可以 增加代码的灵活度
    • 继承重写父类方法 为前提
    • 是调用方法的技巧,不会影响到类的内部设计

    多态案例演练

    需求
    1,在 Dog 类中封装方法 game

    • 普通狗只是能简单的玩耍

    2,定义 XiaoTianQuan 继承自 Dog ,并且重写 game 方法

    • 哮天犬需要在天上玩耍

    3,定义 Person 类,并封装一个 和狗玩 的方法

    • 在方法内部,直接让 狗对象 调用 game 方法

    
        class Dog(object):
            def __init__(self, name):
                self.name = name
        
            def game(self):
                print("普通狗 [%s] :蹦蹦跳跳旺旺旺~~~" % self.name)
        
        
        class XiaoTianQuan(Dog):
            def game(self):
                print("神仙狗 [%s] : 飞天入地吼吼吼~~~" % self.name)
        
        
        class Person(object):
            def __init__(self, name):
                self.name = name
        
            def game_with_dog(self, dog):
                print("[%s] 带着 [%s] 愉快的玩耍" % (self.name, dog.name))
        
                # 让狗玩耍
                dog.game()
        
        
        
        # 1,创建一个狗对象
        # xiaobudian = Dog("小不点")
        xiaobudian = XiaoTianQuan("小不点")
        
        # 2,创建一个人对象
        namei = Person("娜美")
        
        # 3,调用方法
        namei.game_with_dog(xiaobudian)
        
        
        # 结果呈现
        [娜美] 带着 [小不点] 愉快的玩耍
        神仙狗 [小不点] : 飞天入地吼吼吼~~~
    
    

    小结

    • Person 类中只需要让 狗对象 调用 game 方法,而不关心具体是 什么狗
      • game 方法是在 Dog 父类中定义的
    • 在程序执行时,传入不同的 狗对象 实参,就会产生不同的执行结果

    01,类的结构

    1.1 术语 -- 实例

    1,使用面向对象开发,第一步 是设计

    2,使用 类名() 创建对象, 创建对象 的动作有两步

      1. 在内存中为对象 分配空间
      1. 调用初始化方法 __init__对象初始化

    3,对象创建后,内存 中就有了一个对象的 实实在在 的内存 —— 实例

    因此,
    1,创建出来的 对象 叫做 实例
    2,创建对象的 动作 叫做 实例化
    3,对象的属性 叫做 实例属性
    4,对象调用的方法 叫做 实例化方法

    在程序执行时:
    1,对象各自拥有自己的 实例属性
    2,调用对象方法,可以通过 self.

    • 访问自己的属性
    • 调用自己的方法

    结论

    • 每一个对象 都有自己 独立的内存空间,保存各自不同的属性
    • 多个对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用 传递到方法内部

    1.2 类是一个特殊的对象

    Python一切皆对象

    • class AAA: 定义的类属于 类对象

    • obj1 = AAA() 属于 实例对象

    • 在程序运行时, 同样 会被加载到内存

    • python 中, 是一个特殊的对象 --- 类对象

    • 在程序运行时,类对象 在内存中 只有一份 ,使用 一个类 可以创建出 很多个对象实例

    • 除了封装 实例属性方法 外,类对象 还可以拥有自己的 属性方法
      1,类属性
      2,类方法

    • 通过 类名. 的方式可以 访问类的属性 或者 调用类的方法

    02,类的属性和实例属性

    2.1 概念和使用

    • 类属性 就是给 类对象 中定义的 属性
    • 通常用来记录 与这个类相关 的特征
    • 类属性 不会用于记录 具体对象的特征

    示例需求

    • 定义一个 工具类
    • 每件工具都有自己的 name
    • 需求 --- 知道使用这个类,创建了多少个工具对象?

    
        class Tool(object):
        
            # 使用赋值语句定义类属性,记录所有工具对象数量
            count = 0
        
            def __init__(self, name):
                self.name = name
        
                # 让类属性的值 +1
                Tool.count += 1
        
        
        # 1, 创建工具对象
        tool1 = Tool("方天画戟")
        tool2 = Tool("青龙偃月刀")
        tool3 = Tool("涯角枪")
        tool4 = Tool("丈八蛇矛")
        tool5 = Tool("双铁戟")
        tool6 = Tool("古锭刀")
        tool7 = Tool("青釭剑")
        tool8 = Tool("雌雄双剑")
        tool9 = Tool("诸葛连弩")
        
        # 2,输出的工具对象的数量
        print(Tool.count)
        
        # 结果呈现
        9
    
    

    2.2 属性的获取机制

    • python属性的获取 存在一个 向上查找的机制

    • 因此,要访问类属性有两种发式:
      • 类名.类属性
      • 对象.类对象 (不推荐)

    注意

    • 如果使用 对象.类对象 = 值 赋值语句,只会 给对象添加一个属性, 而不会影响到 类属性的值
    
        class Tool(object):
        
            # 使用赋值语句定义类属性,记录所有工具对象数量
            count = 0
        
            def __init__(self, name):
                self.name = name
        
                # 让类属性的值 +1
                Tool.count += 1
        
        
        # 1, 创建工具对象
        tool1 = Tool("方天画戟")
        tool2 = Tool("青龙偃月刀")
        tool3 = Tool("涯角枪")
        tool4 = Tool("丈八蛇矛")
        tool5 = Tool("双铁戟")
        tool6 = Tool("古锭刀")
        tool7 = Tool("青釭剑")
        tool8 = Tool("雌雄双剑")
        tool9 = Tool("诸葛连弩")
        
        # 2,输出的工具对象的数量
        print("对象.类对象 对象总数 %d" % tool6.count)
        tool6.count = 99
        print("对象.类对象 对象总数 %d" % tool6.count)
        print("类名.类属性 对象总数 %d" % Tool.count)
        
        
        # 结果呈现
        对象.类对象 对象总数 9
        对象.类对象 对象总数 99
        类名.类属性 对象总数 9
    
    

    03,类方法和静态方法

    3.1 类方法

    • 类属性 就是针对 类对象 定义的属性
      • 使用 赋值语句class 关键字下方可以定义 类属性
      • 类属性 用于记录 与这个类相关 的特征
    • 类方法 就是针对 类对象 定义的方法
      • 类方法 内部可以直接访问 类属性 或者调用其它的 类方法

    语法如下

    @classmethod
    def 类方法名(cls):
        pass
    
    • 类方法需要用 修饰器 @classmethod 来标识,告诉解释器这是一个类方法
    • 类方法的 第一个参数 应该是 cls
      • 哪一类 调用的方法,方法内的 cls 就是 哪一个类的引用
      • 这个参数和 实例方法 的第一个参数是 self 类似
      • 提示 使用其他名称也可以,不过习惯使用 cls
    • 通过 类名,调用 类方法调用方法时,不需要传递 cls 参数
    • 在方法内部
      • 可以通过 cls 访问类的属性
      • 也可以通过 cls 调用其它的类方法

    示例需求

    • 定义一个 工具类
    • 每件工具都有自己的 name
    • 需求 - - - 在 封装一个 show_tool_count 的类方法,输出使用当前这个类,创建的对象个数

    
        class Tool(object):
        
            # 使用赋值语句定义类属性,记录所有工具对象数量
            count = 0
        
            @classmethod
            def show_tool_count(cls):
                print("类方法: 对象总数 %d" % cls.count)
        
            def __init__(self, name):
                self.name = name
        
                # 让类属性的值 +1
                Tool.count += 1
        
        
        # 1, 创建工具对象
        tool1 = Tool("方天画戟")
        tool2 = Tool("青龙偃月刀")
        tool3 = Tool("涯角枪")
        tool4 = Tool("丈八蛇矛")
        tool5 = Tool("双铁戟")
        tool6 = Tool("古锭刀")
        tool7 = Tool("青釭剑")
        tool8 = Tool("雌雄双剑")
        tool9 = Tool("诸葛连弩")
        
        # 2,输出的工具对象的数量
        print("类名.类属性 对象总数 %d" % Tool.count)
        Tool.show_tool_count()
        
        
        # 结果呈现
        类名.类属性 对象总数 9
        类方法: 对象总数 9
    
    

    在类方法内部,可以直接使用 cls 访问 类属性 或者 调用类方法

    3.2 静态方法

    • 在开发时,如果需要在 中封装一个方法,这个方法:
      • 不需要 访问 实例属性 或者调用 实例方法
      • 不需要 访问 ** 类属性** 或者调用 类方法
    • 这个时候,可以把这个方法封装成一个 静态方法

    语法如下

    @staticmethod
    def 静态方法名():
        pass
    
    • 静态方法 需要用 修饰器 @staticmethod 来标识,告诉解释器这是一个静态方法
    • 通过 类名,调用 静态方法
    
        class Dog(object):
        
            @staticmethod
            def run():
                # 不需要访问实例属性/类属性
                print("小猫要跑。。。")
        
        
        # 通过类名.调用静态方法 - - 不需要创建对象
        Dog.run()
        
        
        # 结果呈现
        小猫要跑。。。
    
    

    3.3 方法综合案例

    需求
    1,设计一个 Game

    2,属性:

    • 定义一个 类属性 top_score 记录游戏的 历史最高分
    • 定义一个 实例属性 player_name 记录 ** 当前游戏的玩家名称**

    3,方法:

    • 静态方法 show_help 显示游戏帮助信息
    • 类方法 show_top_score 显示历史最高分
    • 实例方法 start_game 开始当前玩家的游戏

    4,主程序步骤

    • 查看帮助信息
    • 查看历史最高分
    • 创建游戏对象,开始游戏

    
        class Game(object):
        
            # 类属性
            # 历史最高分
            top_score = 0
        
            # 初始化方法中定义实例属性
            def __init__(self, player_name):
                self.player_name = player_name
        
            # 静态方法
            @staticmethod
            def show_help():
                print("帮助信息:让僵尸进入大门")
        
            # 类方法
            @classmethod
            def show_top_score(cls):
                print("历史最高纪录 %d " % cls.top_score)
        
            # 对象实例方法
            def start_game(self):
                print("%s 开始游戏啦 ..." % self.player_name)
        
        
        # 1,查看游戏的帮助信息
        Game.show_help()
        
        # 2,查看历史最高分
        Game.show_top_score()
        
        # 3,创建游戏对象
        name = Game("小游")
        name.start_game()
        
        
        # 结果呈现
        帮助信息:让僵尸进入大门
        历史最高纪录 0 
        小游 开始游戏啦 ...
    
    

    小结
    1,实例方法 - - 方法内部需要访问 实例属性

    • 实例方法 内部可以使用 类名,访问类属性

    2,类方法 - - 方法内部 需要访问 类属性

    3,静态方法 - - 方法内部 不需要 访问 **实例属性 和 类属性*8

    提问
    如果方法内部 即需要访问 实例属性,又需要访问 类属性,应该定义成什么方法?
    答案

    • 应该定义 实例方法
    • 因为,类只有一个,在 实例方法 内部可以使用 类名,访问类属性
  • 相关阅读:
    中文乱码总结之web乱码情景
    微信小程序实现navbar导航栏
    boostrap table接收到后台返回的数据格式不一致的解决方法
    bootstrap让footer固定在顶部和底部
    在vue中让某个组件重新渲染的笨方法
    网页打印事件的监听
    关于JavaScript的词法作用域及变量提升的个人理解
    函数节流之debounce
    HTML5 a标签的down属性进行图片下载
    Jquery的深浅拷贝涉及到的知识点
  • 原文地址:https://www.cnblogs.com/xiaoqshuo/p/9521821.html
Copyright © 2011-2022 走看看