python面向对象-类与类的关系3

组合关系

组合关系也是关联关系的一种特例,同样体现整体与部分的关系,这种关系比聚合更强

  1. 代表contains-a的关系
  2. 在组合的关系中,彼此依赖的,不可分割
  3. 具有相同的生命周期,整体被销毁,部分也会被销毁

代码:从代码上看,与聚合相同,只能 从语义区分

比如手机和零件的关系,手机是整体,部分是cpu、屏幕、ram、rom,部分之间是不同的。

案例

在上面的购物车代码中,_goods_dict是dict类型,内部还有dict类型的数据,不够优雅,在本例中对购物车代码进行优化

UML类图:

图中所示,Cart类的_cartitems是list类型,元素是CartItem类对象,CartItem类的_goods是Goods类对象

Cart类的_cartitems的 结构 如下图:

Cart类和CartItem类就是组合关系,CartItem和Goods是依赖关系

练习

根据UML类图改造上篇文章的购物车代码:

商品类

class Goods:
    def __init__(self,id,name,price):
        #商品编号
        self._id=id
        self._name=name
        self._price=price

    def get_id(self):
        return self._id

    def get_name(self):
        return self._name

    def get_price(self):
        return self._price

购物车项目类

class CartItem:
    def __init__(self,goods,num):
        self._goods=goods
        self._num=num
    def add_num(self):
        self._num+=1
    def minus_num(self):
        self._num-=1
    def get_num(self):
        return self._num
    def get_goods_id(self):
        return self._goods.get_id()
    def get_goods(self):
        return self._goods

购物车类

class Cart:

    def __init__(self):
        #key是商品编号,value是dict类型的序列,其中key是goods,value是goods对象,key是num,value是数量
        self._cartitems=[]
        #购物车中总共的数量
        self._total_num=0
        self._total_price=0

    def add_goods(self,goods):
        index=self._has_goods(goods)
        if index>=0:
            cartitem=self._cartitems[index]
            cartitem.add_num()
        else:
            cartitem=CartItem(goods,1)
            self._cartitems.append(cartitem)

        self._total_num+=1
        self._total_price+=goods.get_price()

    #伪私有方法,判断商品是否存在,存在返回索引值,不存在返回-1
    def _has_goods(self,goods):
        id=goods.get_id()
        for index,item in enumerate(self._cartitems): 
            if id==item.get_goods_id():
                return index
        return -1

    def remove_goods(self,goods):
        index=self._has_goods(goods)
        #如果存在
        if index>=0:
            cartitem=self._cartitems[index]
            #判断数量是1,就移除
            if cartitem.get_num()==1:
                del self._cartitems[index]
            else:
                cartitem.minus_num()

            self._total_num-=1
            self._total_price-=goods.get_price()

    def get_total_price(self):
        return self._total_price

    def get_total_num(self):
        return self._total_num

    def get_cartitems(self):
        return tuple(self._cartitems)

测试调用

def print_info():
    print("购物车数量:%d,品类:%d,数量:%d,总价:%d,商品:"%(cart.get_total_num(),len(cart.get_cartitems()),cart.get_total_num(),cart.get_total_price()),end="")

    for item in cart.get_cartitems():
        print("id:%s,name:%s,price:%d,num:%s||"%(item.get_goods().get_id(),item.get_goods().get_name(),item.get_goods().get_price(),item.get_num() ),end=",")

    print()

cdb=Goods("001","小米充电宝",100)
dnb=Goods("002","小米电脑包",200)
dnb2=Goods("002","小米电脑包",200)
dnb3=Goods("003","小米电脑包",300)

cart=Cart()
cart.add_goods(cdb)
print_info()
cart.add_goods(dnb)
print_info()
cart.add_goods(dnb2)
print_info()
cart.add_goods(dnb3)
print_info()
cart.remove_goods(dnb2)
print_info()
cart.remove_goods(dnb2)
print_info()

聚合与组合的异同

整体和部分
聚合:整体包含很多个部分,但这里的部分都是相同的。

组合:部分和整体的关系表现为,整体包含该部分,但也包含其他部分,其他部分和该部分并不相同。

生命周期
聚合:拥有各自的生命周期
组合:拥有相同的生命周期

依赖程度
聚合:弱
组合:强

实现关系

抽象类、实现类是java中的概念,在python中也做了借鉴,这里只做介绍。
抽象类:是定义类的行为,定义空方法
实现类:一个类继承某个抽象类后,必须实现该抽象类的所有方法

总结:

  1. 继承和实现是类与类之间的纵向关系
  2. 关联是类与类之间的横向关系
  3. 类与类之间的关系从弱到强依次为:
    依赖 < 关联 < 聚合 < 组合

原文出处:/show_1EF2FwuHPm1b.html