python中的组合和聚合

时间:2013-11-08 14:45:13

标签: python

我想知道如何在python中的 UML术语中实现组合和聚合。

如果我理解:

  1. 聚合:
  2. class B:
        pass
    
    class A(object):
        def __init__(self):
            self.B = B
    

    1. 成分:
    2. 在其他语言中,我看到这个实现为指向B的指针。我猜这里self.B是python中的指针。

      class A(object):
          def __init__(self, B):
              self.B = B
      

      是不是?

3 个答案:

答案 0 :(得分:25)

If I understand correctly,聚合与组合是关于对象对其成员的责任(例如,如果删除实例,是否也删除其成员?)。

主要是,它将在很大程度上取决于实施。例如,要创建一个接收类B(聚合)实例的类A,您可以编写以下内容:

class B(object): pass

class A(object):
    def __init__(self, b):
        self.b = b

b = B()
a = A(b)

但是作为一个提醒点,Python没有任何内置功能可以阻止你传入别的内容,例如:

a = A("string") # still valid

如果您想在A(组合)的构造函数中创建B的实例,您可以编写以下内容:

class A(object):
    def __init__(self):
        self.b = B()

或者,您可以将类注入构造函数,然后创建一个实例,如下所示:

class A(object):
    def __init__(self, B):
        self.b = B()

顺便说一下,至少在你的第一个例子中,可能是第二个例子,你将B设置为B的类定义,而不是它的实例:

class A(object):
    def __init__(self, B):
        self.B = B

>>> a = A()
>>> a.B # class definition
<class __main__.B at 0x028586C0>
>>> a.B() # which you can make instances of
<__main__.B instance at 0x02860990>

所以,你最终会得到一个指向B类定义的A实例,我很确定这不是你所追求的。虽然,这在其他语言中通常要难得多,所以我理解这是否是混淆点之一。

答案 1 :(得分:12)

组合和聚合是Association的特殊形式。关联是两个没有任何规则的类之间的关系。

<强>组合物

在复合中,其中一个类由一个或多个其他类的实例组成。 换句话说,一个类是容器,其他类是内容,如果删除容器对象,那么它的所有内容对象也会被删除。

现在让我们看一下Python 3.5中的组合示例。类Employee是容器,类Salary是内容。

class Salary:
    def __init__(self,pay):
        self.pay=pay

    def get_total(self):
       return (self.pay*12)

class Employee:
    def __init__(self,pay,bonus):
        self.pay=pay
        self.bonus=bonus
        self.obj_salary=Salary(self.pay)

    def annual_salary(self):
        return "Total: "  +  str(self.obj_salary.get_total()+self.bonus)


obj_emp=Employee(100,10)
print (obj_emp.annual_salary())

<强>聚合

聚合是一周形式的构图。如果删除容器对象,则对象可以不带容器对象。

现在让我们看一下Python 3.5中的聚合示例。 Class Employee再次是容器,而类Salary是内容。

class Salary:
    def __init__(self,pay):
        self.pay=pay

    def get_total(self):
       return (self.pay*12)

class Employee:
    def __init__(self,pay,bonus):
        self.pay=pay
        self.bonus=bonus

    def annual_salary(self):
        return "Total: "  +  str(self.pay.get_total()+self.bonus)


obj_sal=Salary(100)
obj_emp=Employee(obj_sal,10)
print (obj_emp.annual_salary())

答案 2 :(得分:2)

# Aggregation is NOT exclusive
class BaseChapter:
    '''
    We can use this BaseChapter in any book, like in OpenBook.
    '''

    def __init__(self, name):
        self.name = name
        self.subject = None
        self.content = None
        return

class OpenBook:

    def __init__(self, isbn):
        self.isbn = isbn
        self.chapters = list()

    def add_chapter(self, obj):

        # This constrain dont have correlation with composition/aggregation
        if isinstance(obj, BaseChapter):
            self.chapters.append(obj)
        else:
            raise TypeError('ChapterError')

# .. but Composition is Exclusive
# Example:
class MyBook:

    class MyChapter:
        '''
        This MyChapter can be used only by MyBook
        '''
        def __init__(self, name, subject):
            self.name = name
            self.subject = subject
            self.title = None
            self.content = None
            self.techincal_refs = list()
            return

    def __init__(self, isbn):
        self.isbn = isbn
        self.chapters = list()

    def add_chapter(self, obj):
        # This constrain dont have correlation with composition/aggregation
        # what is important here is MyChapter can be used only by MyBook
        # a outside object cant create a instance of MyChapter
        if isinstance(obj, self.MyChapter):
            self.chapters.append(obj)
        else:
            raise TypeError('ChapterError')

..是的,我们可以做得更好,比如

class MyBook:

    class MyChapter(BaseChapter):
        '''
        This MyChapter can be used only by MyBook,
        but now is based in BaseChapter.
        But you knhow, python dont create problems if you still want
        create a instance of MyChapter in other 'Books'.

        But when you see this code you will think, This class is exclusive
        to MyBook.
        '''
        def __init__(self, name):
            super().__init__(name)
            self.subject = None
            self.title = None
            self.content = None
            self.techincal_refs = list()
            return

    def __init__(self, nib):
        self.nib = nib
        self.chapters = list()

    def add_chapter(self, obj):
        # This constrain dont have correlation with composition/agregation
        # what is important here is MyChapter can be used only by MyBook
        if isinstance(obj, self.MyChapter):
            self.chapters.append(obj)
        else:
            raise TypeError('ChapterError')