UML 2 For Dummies


Generalizations are a great way to inherit common attributes and operations, but a class inherits much more from a superclass, namely associations, constraints (limits), methods (code for an operation), interfaces (specification of an operation), and composite parts (the parts internal to a class).

Think about an instance of a generic dwelling unit (a superclass) and its associated instance of an address. Now think of a particular kind of dwelling unit, say a ranch style house (a subclass). The ranch unit is also associated with an address because it is a kind of dwelling unit. The ranch unit subclass inherits the dwelling unit’s association with the address class. If you constrain the definition of any dwelling unit’s size attribute to be no smaller than six square feet, then that ranch unit’s size could not be any smaller than six square feet. The ranch unit inherits any constraints of the superclass dwelling unit. You could reuse the dwelling unit’s method for calculating its own resale value based on size and location for calculating the ranch houses resale value based on the same formula. You also inherit the composite parts of a dwelling unit such as the kitchen, living room and bedroom in any type of dwelling like the ranch-style house.

 Warning   You should be careful when inheriting from a superclass. The regulations for using inheritance are a little complex, but we’ll show you the rules that you use most often. When your superclass is associated with other classes, then the subclasses (being special cases of the superclass) are also associated with those same classes. Even so, you should be aware that only certain aspects of an association are inherited. (See the next section, “Making sense of inherited associations,” for more information.) When your subclass specifies constraints, they must be the same as—or more constraining than—those of the superclass. Operations and their methods may be simply reused, or redefined.

Making sense of inherited associations

In the archive example that we used earlier in this chapter, it turns out that storage space—like shelves and file cabinets—store all manner of archive media. Videotapes are stored on special movable shelves. Transcripts are stored in file cabinets of various sizes. To demonstrate this connection, we modeled this situation as an association between the class StorageSpace and the class ArchiveMedium.

All the subclasses of ArchiveMedium inherit this association and so RecordedMedia is associated also with StorageSpace. However, the subclasses of ArchiveMedium only inherit certain features of the association.

You inherit the role name, multiplicity and constraints on the far side of an inherited association. For example, RecordedMedia inherits the multiplicity at the StorageSpace end of the association between ArchiveMedium and StorageSpace. You inherit any constraints and qualifiers on the near side of an inherited association. The near side of the association would be the ArchiveMedium side of the association between ArchiveMedium and StorageSpace.

Figure 6-7 illustrates the far-side features that the subclasses RecordedMedia, PhotoMedia, and PrintMedia inherit from ArchiveMedium in the stores association: 0..1 multiplicity and mediaLocation role name. The subclasses are also forced to be ordered because the stores association has the near-side constraint ({ordered}).

Figure 6-7: Inherited features of an association.

Overriding your inheritance

You can override inheritance—change aspects of inherited attributes, constraints, and the methods used for operations. For example, an attribute of a subclass can redefine an attribute inherited from the superclass. Additionally the method used to implement an operation in a subclass can be a refined version of the operation inherited from the superclass. For example, all types of vehicles (the superclass) can move (the superclass operation). However, each type of vehicle like a sailboat and a car (subclasses) move in very different ways (different subclass methods for the inherited move operation).

Overriding attributes

When overriding attributes inherited by a subclass keep the following in mind with examples illustrated in Figure 6-8:

Figure 6-8: Examples of overridden attributes.

Overriding constraints

Inevitably, you deal with business rules that constrain the objects in your system. For instance, the archivist must follow the rule that no material (ArchiveMedium) may be borrowed from the archive for longer than thirty days. You recognize this as one of those rules people have to follow, and you have to make sure your software doesn’t violate that rule. The archive-system software must warn the archivist when any instance of ArchiveMedium is out for a period close to (but not more than) thirty days.

This case illustrates an important principle: If the superclass has a constraint or limitation, then all of its subclasses have that constraint too. When you use inheritance, your subclasses must not loosen any constraints placed on the superclass. Therefore Books and Transcripts cannot be borrowed for more than thirty days.

Although you can’t loosen the constraint for subclasses, you can tighten it. One example is the rule that Videotapes can’t be borrowed for more than a week.

Overriding operations and methods

One thing we like about inheritance is being able to reuse the method for an operation defined in a superclass. Often the method code for a superclass operation has to be written no more than once; all the subclasses then have that operation. No need to write the method code again (once for each subclass). The original operation of ArchiveMedium has a simple method that works the same for every subclass. The method (using the Java language) looks something like this:

public Boolean original() { if (generation == 1) then return True; //first generation means original else return False; }

Although you can reuse your inherited operations and their methods, you can do more than simply reuse the method code. You can extend, restrict, or optimize your methods. For a concrete idea of these different ways to override methods in the superclass, consider ArchiveMedium and its place operation:

private StorageSpace mediaLocation; //attribute to implement // the association to an instance of StorageSpace public void place (StorageSpace on){ if (on.spaceAvailabe()) //check to see if there is space if (on.add(this)) //add media to storage space mediaLocation= on; //set pointer to our media location }

Now let’s look at what it means to extend, restrict, or optimize a method:

Inheriting interfaces

Classes have public operations that you invoke from instances of other classes. You can think of each one of these public operations as being an interface between you and the internal workings of the class. Each operation is defined by its name, parameters, and return-result type. This definition is known as the operation’s signature. For instance the signature for the assign operation on the ArchiveMedium class includes the name assign, the to argument and its datatype String, as well as the Boolean return result type. In UML the signature for assign looks like this:

assign(to:String): Boolean

Your subclasses inherit this signature as well as the method code for that operation. When you invoke the assign operation on any subclass of ArchiveMedium, your subclasses must all have the assign operation with one parameter—and the operation will return a Boolean value, no matter how you write the method code for the subclasses.

Normally you create instances of classes. Each class has methods defined for each operation. A method must follow the rules laid down by the operation’s signature. The classes used to create instances are known as concrete classes. Most examples of classes in this book are concrete classes. However, suppose you have a superclass operation with no method code for that operation. Such an operation—without method code—is known as an abstract operation. In UML, abstract operations are shown in italics. If an operation is abstract (has no method), then you can’t create instances of that class. The runtime environment wouldn’t know what to do if you invoked an operation that had no method code. In this situation, any of your classes with abstract operations are known as abstract classes. Any class for which you cannot create instances is an abstract class. In UML, abstract classes have their class names shown in italics.

Abstract classes are a great way to enforce interface inheritance. If you specify an abstract operation in a superclass, then all of its subclasses must conform to the signature of that operation. So anyone who inserts a new subclass into the inheritance hierarchy must write method code for the inherited abstract operation to create a concrete subclass.

 Remember   You cannot create instances of abstract classes. You can only create instances of concrete classes.

In Figure 6-9, you see that recommendPlaybackMachine is an abstract operation and RecordedMedia is an abstract class. We don’t have enough information in the superclass to define a method that could recommend what equipment to use to play back recorded media. On the other hand, we have that information in each of the subclasses. Given (for example) an instance of the VideoTape class and a value for its format attribute, we have all the data we need to make a recommendation.

Figure 6-9: An abstract class, used to enforce interface inheritance.


Категории