You can use an association class (also called a link object or link class) when the relationship between two classes needs its own attributes and must exist only while that relationship exists.
What an association class represents
An association connects two classes. An association class is a class attached to that association and represents one specific connection between objects.
For example, a Person can rent a House. The association ends can be named RentedApartments and Tenants. A LeaseContract association class can store information that belongs to the rental relationship rather than to either endpoint:
ApartmentNumberEndDateRent
A LeaseContract therefore represents one PersonâHouse connection. It is not an independently owned contract that you create first and later connect to a person and a house.
When to use one
Use an association class when both of these rules describe the domain:
- The relationship has data. For example, a booking between a person and a flight needs booking-specific data.
- The relationship owns the link object's lifetime. The link object must be created when the two endpoint objects are associated and removed when they are no longer associated.
Association classes are often used on many-to-many associations, but you can use one on an association of any cardinality. See Training:Association classes for the modeling rationale, including lifetime control and uniqueness.
Lifecycle and uniqueness
MDriven controls the lifetime of an association-class object through its association.
| When you do this | What happens |
|---|---|
Add a House to a Person's RentedApartments
|
MDriven creates the corresponding LeaseContract link object.
|
Add a Person to a House's Tenants
|
MDriven creates the corresponding LeaseContract link object.
|
Remove the house from RentedApartments, or remove the person from Tenants
|
MDriven removes the corresponding LeaseContract link object.
|
Do not treat the association-class object as independently createable or removable. To remove a LeaseContract, remove one endpoint from the association. For example, remove the tenant from the house's Tenants collection. The contract then loses the relationship that gives it a right to exist and is removed by the framework.
An association class also communicates uniqueness: one endpoint pair represents one link object. For example, you cannot add the same person to the same flight twice and obtain two separate bookings for that same pair.
Add an association class in MDriven Designer
- Create or select the association between the two endpoint classes.
- In the diagram toolbar, select the dotted-line tool whose tooltip says drag-out new association class connection.
- Drag from the association to the class that will represent the link object, or select the association when prompted.
- Select the association line and verify the selected association class in the Property Inspector.
- Add attributes and operations to the association class. For example, add
EndDateandRenttoLeaseContract.
To detach the association class, select the association line and choose no association class in the Property Inspector.
Diagram removal is not model deletion
When you show existing classes in a new diagram, MDriven Designer can also show their association and association class. If you do not want to show it in that diagram, select it and press Delete. This removes it from the diagram only.
Ctrl+Delete removes the selected item from the model. Do not use Ctrl+Delete when you only want to change the diagram layout.
An association class gives you two useful ways to navigate:
- Direct endpoint navigation follows the normal association. For example,
aHouse.Tenantsreturns the people renting the house. - Link-object navigation reaches the association-class objects. From a house, this returns its lease contracts; from each lease contract, you can continue to its one tenant and one house.
Set names for both parts of this navigation on each association end:
| Name | Navigation it controls | Example from House |
|---|---|---|
| LinkRoleName | From an endpoint to the association-class objects | aHouse.LeaseContracts
|
| InnerLinkName | From an association-class object onward to the endpoint at that association end | aLeaseContract.TenantOfLease
|
Select an association end in MDriven Designer and set its LinkRoleName and InnerLinkName in the Property Inspector. Name both directions deliberately. The default names may be unclear, especially where a collection name and a single-object name are both needed.
For the rental example, readable names could be:
| Starting class | LinkRoleName | Starting from LeaseContract | InnerLinkName |
|---|---|---|---|
| House | LeaseContracts
|
LeaseContract to its House | HouseOfLease
|
| Person | LeaseContracts
|
LeaseContract to its Person | TenantOfLease
|
The inner navigation is normally singular because one LeaseContract refers to one object at each end. For example, use TenantOfLease, not TenantsOfLease.
OCL can follow either the direct association or the link-object route.
With the example names above:
-- Directly obtain the people associated with a house
aHouse.Tenants
-- Obtain the link objects for a house
aHouse.LeaseContracts
-- Continue from each link object to its tenant
aHouse.LeaseContracts.TenantOfLeaseUse the link-object route when you need an attribute on the relationship. For example, select lease contracts by their EndDate rather than selecting houses or people alone.
Add and use the created link object
Add an endpoint object to the association, then work with the link object that MDriven created. For a PersonâFlight association with Booking as its association class, the following pattern adds a flight and retrieves its booking:
self.Flights.add(aFlight);
self.Bookings->select(b | b.Flight = aFlight)->firstWhen you need the created object immediately, use addReturnIndexOf0 to obtain the zero-based position of the added endpoint and retrieve the corresponding link object:
self.Bookings.at0(self.Flights.addReturnIndexOf0(aFlight)).AttributeOnBookingThis pattern is particularly useful in an operation when you must set an attribute on the new link object, such as a booking-specific value. For the full adding pattern and naming guidance, see Documentation:Adding a link object.
Remove the correct object from the correct link
A common error is to try to remove the link object from the endpoint association. The endpoint association expects an endpoint object, not an association-class object.
For example, if vCurrentHouse.Tenants expects a Person, this is the intended removal shape:
vCurrentHouse.Tenants.remove(vCurrentLeaseContract.TenantOfLease)The expression first follows the inner link from the selected LeaseContract to its Person. Removing that person from Tenants removes the association, so MDriven removes the associated LeaseContract automatically.
Association class versus an ordinary class with two associations
You can model a LeaseContract as an ordinary class with one association to Person and another to House. This can produce a similar relational database shape, but it does not express the same object-model rule.
With an association class, the contract is tied to the PersonâHouse association and receives automatic lifecycle control. With an ordinary class, its creation and deletion are not governed by that association in the same way. Choose an association class when the relationship itself owns the object's existence.
