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

Viewed 150

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)
2 Answers

In your own answer you claim that A_B is an association class. This is indeed a valid interpretation.

But it's not the only one:

An Association declares that there can be links between instances whose types conform to or implement the associated types. A link is a tuple with one value for each memberEnd of the Association, where each value is an instance whose type conforms to or implements the type at the end. (section 11.5.3.1)

Your python class A_B fully meets this definition: it implements such a link between the associated types. In fact, it provides nothing more an nothing less than the functionality of a tuple (in the abstract sense).

The classes of your model are not necessarily related one to one to your implementation classes. Modelling means to take a viewpoint on the world. The story of the elephant and the blind persons tells us, there are often several valid view points. So, up to you to chose the one which helps you best to solve your problem.

Additional remark: Classes like A_B are frequently used to implement many-to-many associations. A similar choice exists when ternary associations are involved: some prefer to see them as a binary association class having an association with a third class. Some prefer to see it as a simple N-ary association. Both would probably be implemented with using an class A_B_C in the implementeation language.

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
Related