python中的组合与聚合

2024-05-29 07:46:46 发布

您现在位置:Python中文网/ 问答频道 /正文

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

如果我明白了:

  1. 聚合:

class B:
    pass

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

  1. 组成:

在其他语言中,我把它看作是指向B的指针,我猜这里self.B是python中的指针。

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

对吗?


Tags: self语言objectinitdefpassclass指向
3条回答

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

组成

在组合中,一个类由其他类的一个或多个实例组成。 换句话说,一个类是container,另一个类是content,如果删除container对象,那么它的所有contents对象也将被删除。

现在让我们看看Python3.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())

聚合

聚合是一种弱组合形式。如果删除容器对象,则对象可以在没有容器对象的情况下生存。

现在让我们看看Python3.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

    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())
# 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')

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(composition)的构造函数中创建B的实例,可以编写以下内容:

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

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

class A(object):
    def __init__(self, B):
        self.b = 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实例,我很确定这不是你想要的。不过,在其他语言中,这通常要困难得多,所以我明白这是否是一个困惑的地方。

相关问题 更多 >

    热门问题