Search code examples
inheritanceumlaggregationcomposition

How to guarantee that class specializations are consistent


I have two Abstract Classes, representing an composition:

  • Country (made of People)
  • People

I have a concretization of these two classes in e.g.:

  • Country: France and Italy
  • People: FrenchGuy and ItalianGuy

The Country abstract class as a list of people as an attribute: peopleList:People

How can I guarantee that the France class peopleList attribute will be filled only with FrenchGuy, and Italy with ItalianGuy, and make it consistent ?

Does the way how I designed it is an anti-pattern ?

enter image description here

Thanks in advance for your answers


Solution

  • I will answer this question with an example that does not confuse "is a kind of" with "is an instance of". (Please see my comments on the original question for more detail.)

    You can, indeed, guarantee that specific specializations are only associated with certain other specializations. You can do this using UML association specialization and property redefinition.

    redefinition example diagram

    I'll give you a tour of what this UML diagram tells us:

    • There is an unnamed association between Insurance Policy and Insurable Thing that has two properties: insures and insured by. It tells us that, in general, each Insurance Policy insures one or more Insurable Things, and each Insurable Thing may be insured by any number of Insurance Policies
    • An Insurance Policy has two disjoint² specializations: Health Insurance Policy and Car Insurance Policy.
    • An Insurable Thing has two disjoint specializations: Car and Person.
    • The unnamed association at the top has two specialized associations with more specific property constraints:
      • The association between Car Insurance Policy and Car has properties that redefine (i.e., tighten) their allowed types.
      • The association between Health Insurance Policy and Person has properties that redefine (i.e., tighten) their allowed types.

    The specialized associations and the redefinitions are doing all the work here. If you like, you could further tighten the multiplicities or even change the property names³.


    ¹ Note that UML recently adopted a "dot notation" that makes the absence of dots on the ends of an association ambiguous. Pre dot notation, a navigable property was owned by the class on the other end of the association. Post dot notation, a navigable property is owned by the association--except for the fact that few tools support it, and those that do, such as MagicDraw, turn the dots off by default in the project options! I personally find the dot notation horrid, so this example does not use it, which means the properties are owned by the class on the opposite end of its association.

    ² Disjoint means that nothing can be an instance of both specializations, which many implementation languages disallow, but the real world and UML do allow. Incomplete means that there could be other kinds of insurance policies that we haven't called out and it is possible to directly instantiate the general Insurance Policy.

    ³ If you change a property name, what that means is that, in the context of its owner, that name eclipses the name in the generalized owner. If you "upcast" the specialization, the same property will be have its original name because it is in the context of the generalized owner.