I frequently see modelers using abstract signatures with no fields in their models. The abstract signatures usually have subsignature extensions but no fields. For instance, consider the following model from Jackson's book on Alloy:
abstract sig A {}
sig A1 extends A {}
sig A2 extends A {}
With no fields, how is A used after declaration? What is the point of making A abstract and how would the model be constrained differently if A was not abstract?
You're right that the greatest value for an abstract sig comes when it has a field. And because Alloy has unions, you can write A1+A2 instead of A. But even if it doesn't, there are advantages: by declaring A as an abstract sig, I can make my model easier to change. If I added a new sig A3, I would have to replace A1 + A2 by A1 + A2 + A3, but with an abstract sig, it's still A. It also gives me a place to add a field later, and it makes specs shorter. And it allows me to give a scope to it; if I only had A1 and A2, I would have to set their scopes separately, but setting a scope of A to 5 (say) allows the analyzer to allocate the atoms in any ratio between A1 and A2. And in visualization, I can apply settings to A explicitly.
Related
Given a class inheritance hierarchy:
which says:
class S inherits A1 and A2
class A1 and A2 inherits B1
class A2 inherits B2
class B2 inherits C1
and for class A1, B1, B2, C1, they have classifierBehavior attribute setted, while
the class S has no classiferBehavior.
Now the question is, when I run simulation for class S, then what behavior should be executed?
In Cameo Systems Modeler, the simulation engine will execute classifier behavior of A1, B1, and B2.
Is this the correct way and can be derived from UML spec?
The UML specification doesn't tell us how to deal with multiple inherited classifierBehaviors. However, the fUML specification says:
fUML 1.5 (page 151): [5] startBehavior [...] create a classifier behavior invocation for each of the types of the object of this object activation which has a classifier behavior [...].
So, I think the Cameo simulation engine works as specified, since the supertypes are in the list of types an object has. And, it really makes sense. If something is of two types, it should exhibit the behavior of both types. For example an inverter-charger will react to the events an inverter and a charger reacts to.
One thing I didn't find in the specification is, that when a Class has a classifierBehavior, the inherited behaviors should be replaced by it. I think it makes sense, because otherwise the inherited behaviors could never be changed. The simulation engine does exactly this.
Now, it is possible, that you want to select one of the inherited behaviors instead of defining a new one or executing them concurrently. This could be done by defining an empty Behavior with a generalization to the inherited classifierBehavior and assign this as classifierBehavior. This doesn't work in the simulation engine though. fUML excludes redefinition of ActivityNodes, so this could be an explanation why Activity generalization doesn't work. However, the "Precise Semantics of State Machines" specification allows redefinition of states.
So the only way I found was to create a new classifierBehavior and call one of the inherited behaviors.
The situation for resolving the method of an operation is different. For example it could have an output. Here only the modeler can decide, which output shall be returned. This is done by defining a new version of the operation that redefines both old versions and select the behavior from the desired ancestor as method of the new operation. I think this is fairly straight forward and no reason for rejecting multiple inheritance.
I skimmed the UML 2.5 specs and found this paragraph on p. 288:
If the Class of the receiving object owns a method for the Operation identified in the CallEvent, then that method is the result of the resolution. Otherwise, the superclass of the Class of the receiving object is examined for a method for the Operation, and so on up the generalization hierarchy until a method is found or the root of the hierarchy is reached. If a Class has multiple superclasses, then all of them are examined for a method. If no method is found, or a method is found in more than one ancestor Class along different paths, then the model is ill-formed for this resolution process and it results in no method.
So there you are. It's not valid to have multiple behaviors defined. Other than that you can/must override the behavior with something new.
Suppose you have an excerpt of a larger profile for cars:
Now i want to define some constraints for a Car, say one of those constraints states, that if attrA is true, then attrB must be false like this using OCL:
Context UML::Core::Class inv:
self
.stereotype
.name='Car'
implies
self.attrA=true
implies
self.attrB=false
My question is: If the Mercedes stereotype specializes the Car stereotype do I stick to the same constraints, in other words: is the stereotype Car still applied for classes that have the Mercedes stereotype applied?
I would suppose that self.stereotype.name='Car' return false if the applied stereotype is Mercedes.
This is interesting because I want to have the same attributes on a Mercedes as on a Car, but i want to change the previously stated constraint.
I would suppose that self.stereotype.name='Car' return false if the applied stereotype is Mercedes.
Yes you are right.
Mercedes inherits the constraint as it is, so self.stereotype.name='Car' is false for a class stereotyped Mercedes rather than Car because 'Mercedes' and 'Car' are two different strings.
If you want to have the first implies active for the metaclasses specializing Car directly or indirectly you can get all the generalizations of the stereotype more itself to search for one named 'Car', also checking the name of the profile of the stereotype and may be its URI. So for instance replace self.stereotype.name='Car' by :
self.stereotype.profile.name = 'Cars' and
-- self.stereotype.profile.URI= '...' and
self.stereotype.generalization()
->closure(general.generalization).general()
->including(self.stereotype)
->select(name = 'Car')
->notEmpty()
or with an alone profile named Cars and an alone stereotype in it named Car :
self.stereotype.oclIsKindOf(Profile.allInstances()
->any(name = 'Cars') -- may be check also URI
.ownedStereotype->any(name = 'Car'))
Additional notes :
in your proposal you suppose only your stereotype is named Car among all the stereotypes of all the profiles, of course that can be false. You can also check the name of the profile and may be its URI like:
self.stereotype.name='Car'
and self.stereotype.profile.name='Cars'
-- and self.stereotype.profile.URI= '...'
in your diagram the arrow head is wrong because it must be a filled triangle rather than < (probably you use PlantUML) :
If you think about it, what you ask is unreasonable.
Suppose your system already has the over-enthusiastic constraint that a Car's FuelType is PETROL. You are in big trouble trying to define a derived Car whose FuelType is DIESEL; it would not be a Car wrt to the modelled definition of Car.
You could try to workaround the problem with mixins, but the number of permutations would be intolerable for any practical production Car.
Instead you can take the approach of loopholes adopted by the UML specification exemplified by the Namespace.isDistinguishable helper that determines whether unique names are required or not (multiple unnamed Constraints are permitted).
Therefore for Car you could define the getAcceptableFuelTypes() helper that can be overridden to create a loophole for derived classes; implement your base constraint as getAcceptableFuelTypes()->includes(fuelType).
Imagine the following case: I have a class Method and a class DataType. A method has one return type (if we count void as a return type) and zero to many parameters. Both the return type and the parameters are instances of the class DataType.
How would I model this Situation in a UML class diagram? One line for two references or one for each?
Solution A, one line:
Solution B, two lines:
The best way would be to use role names instead:
Role names are explicit attributes in the opposite class, telling how the specific class is used. So Method.parameter is of type DataType.
Note that I changed the return type to be 0..1 rather than 1 since your text tells that it's optional.
Is it possible to connect a1 with b1 twice on (object diagram), while A has only one B object and it is {nonunique}?
nonunique constraint has sense only if upper multiplicity is higher than zero (while of course you are still allowed to use it anyway). It means that in a particular association with a specific object the same object on the other side can be used more than once.
I believe that's what you wanted to achieve, however the constraint should be on the other end of the association (the one with multiplicity *).
Your diagram shows just classes. Objects have an underlined name and usually do not show compartments.
The {nonunique} constraint in the multiplicity just tells that B must not be unique.
The double association between a1 and b1 is absolutely legal. However, without a role name it's rather pointless and a single association would be enough.
What is the difference between association and dependency? Can you give code examples?
What is the relationship between class A and B?
class A
{
B *b;
void f ()
{
b = new B ();
b->f();
delete b;
}
}
The short answer is: how any specific source language construct should be represented in UML is not strictly defined. This would be part of a standardized UML profile for the language in question, but these are sadly few and far between. Long answer follows.
In your example, I'm afraid I would have to say "neither", just to be difficult. A has a member variable of type B, so the relationship is actually an aggregation or a composition... Or a directed association. In UML, a directed association with a named target role is semantically equivalent to an attribute with the corresponding name.
As a rule of thumb, it's an aggregation if b gets initialized in A's constructor; it's a composition if it also gets destroyed in B's destructor (shared lifecycle). If neither applies, it's an attribute / directed association.
If b was not a member variable in A, and the local variable b was not operatoed on (no methods were called on it), then I would represent that as a dependency: A needs B, but it doesn't have an attribute of that type.
But f() actually calls a method defined in B. This to me makes the correct relationship a <<use>>, which is a more specialized form of dependency.
Finally, an (undirected) association is the weakest form of link between two classes, and for that very reason I tend not to use them when describing source constructs. When I do, I usually use them when there are no direct source code relationships, but the two classes are still somehow related. An example of this might be a situation where the two are responsible for different parts of the same larger algorithm, but a third class uses them both.
It may be useful to see this question I asked: does an association imply a dependency in UML
My understanding is:
Association
public class SchoolClass{
/** This field, of type Bar, represents an association, a conceptual link
* between SchoolClass and Student. (Yes, this should probably be
* a List<Student>, but the array notation is clearer for the explanation)
*/
private Student[] students;
}
Dependency
public class SchoolClass{
private Timetable classTimetable;
public void generateTimetable(){
/*
* Here, SchoolClass depends on TimetableGenerator to function,
* but this doesn't represent a conceptual relationship. It's more of
* a logical implementation detail.
*/
TimetableGenerator timetableGen = new TimetableGenerator();
/*
* Timetable, however, is an association, as it is a conceptual
* relationship that describes some aspect of the data that the
* class holds (Remember OOP101? Objects consist of data and operations
* upon that data, associations are UMLs way or representing that data)
*/
classTimetable = timetableGen.generateTimetable();
}
}
If you want to see the difference at the "code level", in an association between A and B, the implementation of A (or B or both depending on cardinalities, navigability,...) in an OO lang would include an attribute of type B.
Instead in a dependency, A would probably have a method where one of the parameters is of type B. So A and B are not linked but changing B would affect the dependant class A since maybe the way the A method manipulates the object B is no longer valid (e.g. B has changed the signature of a method and this induces a compile error in the class A)
Get it from Wiki: Dependency is a weaker form of relationship which indicates that one class depends on another because it uses it at some point of time. One class depends on another if the latter is a parameter variable or local variable of a method of the former. This is different from an association, where an attribute of the former is an instance of the latter.
So I think the case here is association, if B is a parameter variable or local variable of a method of the A, then they are dependency.
A dependency really is very loosely defined. So there would be no code representation.
Wiki: A dependency is a semantic relationship where a change to the influent or independent modeling element may affect the semantics of the dependent modeling element.[1]
From the OMG Spec: A dependency is a relationship that signifies that a single or a set of model elements requires other model elements for their specification or implementation. This means that the complete semantics of the depending elements is either semantically or structurally dependent on the definition of the supplier element(s).