One weird thing about UML is that there aren’t collection types or array types. Basically, multiplicity and typing are totally independent concerns, represented by the metaclasses TypedElement and MultiplicityElement.
A typed element is a named element that has a type, and that is all about it. Examples of typed elements are value specifications, properties, parameters, pins and variables.
A multiplicity element, on the other hand, is an element that when instantiated potentially admits a collection of values. An optionally defined lower bound value (defaults to 1) can determine the minimum number of instances expected. Whether multiple values are in fact admitted will depend on the upper bound of the multiplicity element, which defaults to 1 (no multiple values allowed), but can be set to any positive integer, or infinity. A multiplicity element that can actually be multivalued can also be characterized regarding ordering (whether values can be accessed by position) and uniqueness (whether values can be repeated).
Some kinds of elements are both typed and support multiplicity (such as properties, parameters, pins and variables), however a few are one or the other (let’s ignore those in this discussion).
Mapping UML to Java
To try to illustrate all that was said above, let’s see a few examples of Java variable declarations and the equivalent declaration in UML (using TextUML syntax):
declaration | Java | TextUML |
---|---|---|
single-valued | Client c |
c:Client |
multi-valued | Collection<Client> c |
c:Client[*] |
Client[] c |
||
ordered | List<Client> c |
c:Client[*]{ordered} |
unique | Set<client> c |
c:Client[*]{unique} |
There are few interesting differences though:
- in UML, it is the typed element itself that defines multiplicity, and not the type
- c:Client, c:Client[1] and c:Client[1,1] are all equivalent
- c:Client[*], c:Client[1,*] are equivalent
- if a value is optional, the lower bound must be specified to be 0 (example: c:Client[0,1]). There is no Java equivalent for that.
- unique and unordered are the default in UML (you can use the modifiers ‘nonunique’ and ‘ordered’ to override the defaults)
There are some implications related to assignment when the source and destination are multiplicity elements:
- the upper bound of the destination must be the same or greater than the upper bound of the source, or a type mismatch will ensue
- what happens if source and destination differ on ordering or unicity? The UML spec does not sem to cover that (let me know if you think otherwise). In TextUML, any required transformations are performed automatically behind the scenes. For example: if the source is non-unique and the destination is unique, duplicates will be silently suppressed, or if the source is unordered and the destination is ordered, an arbitrary order will be defined.
Well, that was it for today. If you have questions, suggestions or think I got something wrong here, feel free to add a comment.