Hello again,
I think there's a bit of confusion in this thread between the
definition of UML and the
application of UML.
In the definition of UML, there is a subtype of Classifier called DataType, which in turn has subtypes PrimitiveType and Enumeration, each with their own characteristics. A characteristic of PrimitiveType is that it may not have an internal structure.
In the application of UML, ie a model in the UML language, there is no DataType or PrimitiveType -- but there may be «dataType»s and «primitive»s. Here, the fact that a «primitive» is not permitted to contain attributes means that it cannot be the source of a generalization (unless the target is also a «primitive»), since a generalization inherits the attributes of the target.
That's fine, but you can't use Generalizations between domains. The correct relationship in that case would be Realization: a C# float realizes a real number.
I think this quote encapsulates the problem.
The definition of Primitive Type suggests a change of domain (bold emphasis below) but it is also ambiguous (italics emphasis below) because it refers to DataTypes and implies that a PrimitiveType is more abstract than a DataType (a PrimitiveType has no structure but a DataType has).
10.2.3.2 Primitive Types
A PrimitiveType defines a predefined DataType, without any substructure. A PrimitiveType may have algebra and operations defined outside of UML. The run-time instances of a PrimitiveType are values that correspond to mathematical elements defined outside of UML (for example, the Integers).
Not quite. Neither DataType nor PrimitiveType are abstract; they are both concrete. What this means is that in a UML model, you are allowed to create «dataType»s and «primitive»s, but not «classifier»s because in the UML definition, Classifier is abstract.
DataType is, however,
more general than PrimitiveType. In a UML model, all «primitive»s are also «dataType»s; wherever a «dataType» is required, you may use a «primitive». But the opposite does not hold true: if a «primitive» is required somewhere you may not substitute a non-primitive «dataType». That is what the metamodel relationship means, and that is
all the metamodel relationship means.
The correct relationship in that case would be Realization: a C# float realizes a real number.
My brain hurts less with the concept of realization.
However, this statement from Chapter 10 makes my brain hurt:
A PrimitiveType defines a predefined DataType, without any substructure.
The first headache is the use of the word "defines", if a PrimitiveType defines a DataType, the generalization seems to be the wrong way around because PrimitiveTypes are structureless and therefore more abstract than DataTypes. As pointed out by Uffe and qwerty, there is nothing to inherit (other than relationships to other elements). From this angle, I agree with Geert.
(Emphasis added.)
Again, I think it's the definition vs application that's tripping you up.
A «primitive» is not more general because it has no attributes (we dealt with abstractness vs generalness above). The number of attributes is not a measure of generalness; the only measure of generalness is a classifier's position in a chain of generalizations. The nearer to the ultimate source, the more general. In the UML definition, DataType is more general than PrimitiveType, but Classifier is more general still.
The language in the spec simply emphasises the fact that «primitive»s are also «dataType»s. In the corresponding text for Enumerations, the same notion is expressed using different language: "Enumeration is a kind of DataType." Is a kind of -- defines a. Same thing.
The second headache is the use of the word "predefined", if DataTypes are predefined, the generalization could be the right may around because DataTypes come first and PrimitiveTypes are just used to classify DataTypes.
I hear you, but that can't be the intended reading of "predefined." If they were truly predefined, you should not be able to create new ones -- in other words, no «primitive»s in an applied UML model, just Boolean, Integer, Real, String and UnlimitedNatural.
I think what's intended here is rather "externally defined." Meaning that there is an external (external to the model) definition which can be as complex as you wish, but the complexity is not captured in the UML model -- a «primitive» ComplexNumber could be an example of this.
Just to make the whole thing more entertraining, Chapter 21 of the UML specification states
The PrimitiveTypes package is an independent package that defines a set of reusable PrimitiveTypes that are commonly used in the definition of metamodels. The UML metamodel uses the PrimitiveTypes package." It also refers to them as "domains" and enumerates 5 of them: Integer, Boolean, String, UnlimitedNatural and Real. Unfortunately none of the examples are about how to use them to "extend" data types.
This quote also implies the relationship is the other way around.
Again, I don't see this.
Chapter 21 defines five «primitive»s and states, quite unequivocally, that they cannot be drawn in a diagram -- there "is no notation". And this is in fact how they are implemented in EA. You can use them as attribute types, but they aren't elements that you can place in diagrams. And since they aren't elements you can't specialize them.
To sum up, it's important to keep track of what domain you're in. Are you in the MOF domain, defining UML, with DataType and PrimitiveType and Enumeration?
Or are you in the UML domain, with «dataType»s, «primitive»s and «enumeration»s?
And if you are in the UML domain, is your model a conceptual one or an implementation one?
My brain hurts.