• 类与对象-组合


    1. 计算有多少个实例化对象调用了一个类
    class A:
    
        count = 0
    
        def __init__(self):
            A.count += 1
    
    a1 = A()
    a2 = A()
    print(A.count)      # 2

    2. 组合就是将一个对象封装到另一个对象的属性中

    class Game_role:
    
        def __init__(self, name, ad, hp):
            self.name = name
            self.ad = ad
            self.hp = hp
    
        def attack(self, obj2):
            print("%s攻击了%s, %s掉了%s血,还剩%s血" % (self.name, obj2.name, obj2.name, self.ad, obj2.hp-self.ad))
    
    
    
    class Weapen:
    
        def __init__(self, name, ad):
            self.name = name
            self.ad = ad
    
        def weapen_attack(self, p1, p2):
            # 这里表示会受到人和武器的双重伤害
            p2.hp -= self.ad + p1.ad
            print("%s利用%s攻击了%s%s还剩%s血" % (p1.name, self.name, p2.name, p2.name, p2.hp))
    
    # 实例化两个游戏角色对象
    p1 = Game_role("盖伦", 10, 100)
    p2 = Game_role("剑豪", 20, 80)
    # 实例化一个武器对象
    pillow = Weapen("枕头", 2)
    pillow.weapen_attack(p1, p2)
    
    # 运行结果:
    盖伦利用枕头攻击了剑豪,剑豪还剩68

    3. 上面的示例中有个奇怪的地方,就是实例化一个武器对象 pillow 后,它调用了 weapen_attack() 方法,也就是这个武器作为发起者。按照正常逻辑来说,应该是人发起攻击才合理

    class Game_role:
    
        def __init__(self, name, ad, hp):
            self.name = name
            self.ad = ad
            self.hp = hp
    
        def attack(self, obj2):
            print("%s攻击了%s, %s掉了%s血,还剩%s血" %
                  (self.name, obj2.name, obj2.name, self.ad, obj2.hp-self.ad))
    
        def equip_weapen(self, w):
            # 给对象封装一个属性,该属性是另一个类的对象
            self.w = w
    
    class Weapen:
    
        def __init__(self, name, ad):
            self.name = name
            self.ad = ad
    
        def weapen_attack(self, p1, p2):
            p2.hp -= self.ad + p1.ad
            print("%s利用%s攻击了%s%s还剩%s血" %
                  (p1.name, self.name, p2.name, p2.name, p2.hp))
    
    p1 = Game_role("盖伦", 10, 100)
    p2 = Game_role("剑豪", 20, 80)
    pillow = Weapen("枕头", 2)
    
    print(p1.__dict__)
    # 运行结果:
    {'name': '盖伦', 'ad': 10, 'hp': 100}
    
    # 这里是重点,pillow 是另一个类 Weapen 的实例化对象
    # 此时类 Game_role 的一个实例化对象 p1 调用类的方法 equip_weapon 时
    # pillow 作为参数传进去,相当于是一个人 p1 "装备了" pillow "这个武器"
    # 也就是说,p1 这个实例化对象多了一个属性 pillow
    p1.equip_weapen(pillow)
    print(p1.__dict__)
    # 运行结果:
    {'name': '盖伦', 'ad': 10, 'hp': 100, 'w': <__main__.Weapen object at 0x7fa8ca1265f8>}
    
    # 根据上面的字典可知,此时,p1.w 就是指向实例化对象 pillow 在内存中的地址
    # 也就是或, p1.w = pillow
    # 而在上一个示例中,pillow 调用类 Weapen 的方法是这样:
    # pillow.weapen_attack(p1, p2)
    # 相当于 p1.w.weapen_attack(p1, p2)
    p1.w.weapen_attack(p1, p2)
    # 运行结果:
    盖伦利用枕头攻击了剑豪,剑豪还剩68# 现在看起来就像是 p1 发起的攻击,在逻辑上也更合理了

    4. 组合的好处:

    • 使代码的逻辑更合理
    • 就是为了解耦,让程序的各个角色之间相互独立,再增加两个独立的角色之间 的关联性
    class User:
    
        def __init__(self, name):
            # 每一个用户都有自己名字,所以要放在这里
            self.name = name
            self.order_list = []
    
    class Order:
    
        def __init__(self, o_id):
            self.o_id = o_id
            self.goods_list = []
    
    class Goods:
    
        def __init__(self, name, price):
            self.name = name
            self.price = price
    
    apple = Goods("苹果", 5)
    banana = Goods("香蕉", 3)
    o1 = Order(1)
    o1.goods_list.append(apple)
    o1.goods_list.append(banana)
    print(o1.goods_list)
    # 运行结果:
    [<__main__.Goods object at 0x7f03744ef630>, 
     <__main__.Goods object at 0x7f03744ef6a0>]
    class Order:
    
        def __init__(self, o_id):
            self.o_id = o_id
            self.goods_list = []
    
    o1 = Order(1)
    o1.goods_list.append(["苹果", 5])
    o1.goods_list.append(["香蕉", 3])
    # 如果还有一个对象 o2
    o2 = Order(2)
    o2.goods_list.append(["苹果", 5])
    
    # 如果苹果降价了,变为 4 元,那么 o1、o2 都得一个一个变
    # 而在上面的程序中只需改变 apple.price 的值即可
    # 所以组合就是让程序的各个角色之间相互独立,再增加两个独立的角色之间的关联性
    
    print(o1.goods_list)        # [['苹果', 5], ['香蕉', 3]]
  • 相关阅读:
    大概了解了flexbox
    JS基础知识
    bugzilla_firefox
    Redis的五种数据类型
    Redis交互编程语言及客户端
    为什么要用Thrift
    知识产权代理行业公司竞争分析
    @Resource和@Autowired的区别
    Maven 3.3全局配置
    Aspose for Maven 使用
  • 原文地址:https://www.cnblogs.com/zyqui/p/12454841.html
Copyright © 2020-2023  润新知