Search code examples
oopumlassociationsclass-diagram

How can an association end be association-owned and navigable in UML?


The UML 2.5.1 specification states about association-end ownership:

  • Dot notation is used to denote association end ownership, where the dot shows that the Class at the other end of the line owns the Property whose type is the Class touched by the dot.

And it states about association-end navigability:

  • Arrow notation is used to denote association end navigability. By definition, all class-owned association ends are navigable.

I can clearly see why an association end that is class-owned is navigable:

class A:
    def __init__(self, b):
        self.b = b  # class-owned

class B:
    pass

b = B()
a = A(b)
a.b  # navigable

However I have more trouble figuring out how an association-end that is association-owned (so not class-owned) could be navigable?

The specification states that associations can be represented with association classes:

An AssociationClass can be seen as an Association that also has Class properties, or as a Class that also has Association properties.

So I tried to implement the association with a Python class (like in SQL where associations are often implemented with SQL association tables when the association ends are association-owned), but without much success:

class A:
    pass

class B:
    pass

class A_B:  # association class
    def __init__(self, a, b):
        self.a = a  # association-owned
        self.b = b  # association-owned

b = B()
a = A()
a_b = A_B(a, b)
a.b  # not navigable (AttributeError)

Solution

  • The solution was to set the association link as an attribute of the class, as suggested by @qwerty_so and this article:

    class A:
        def link(self, b):
            self.a_b = A_B(self, b)  # set attribute
    
    class B:
        pass
    
    class A_B:  # association class
        def __init__(self, a, b):
            self.a = a  # association-owned
            self.b = b  # association-owned
    
    b = B()
    a = A()
    a.link(b)
    a.a_b.b  # navigable