In daily life we classify things into various classes. We know the differences between cats and dogs, streets and houses, triangles and circles; they all are different classes. Classification is often based on appearance and behavior.
Furthermore, classes may be grouped into categories. Cats and dogs are belonging to the category of mammals, triangles and circles are belonging to the category of geometric figures. A category represents a set of classes. A class may belong to more than one category. For example, cats and dogs are not only belonging to the category of mammals, they also belong to the category of domestic animals together with fowls as hens and geese.
In this chapter we will examine the concepts of categories and will describe how categories can be defined and used in Elisa.
A category is characterized by a type and by category operations. The type specifies the set of classes belonging to the category. For example, a Vehicle may be a Car, a Motorcycle, or a Truck. In that case, Vehicle is the name of a category which consists of the classes Car, Motorcycle, and Truck. This may be specified as:
type Vehicle = category (Car, Motorcycle, Truck);
This type specification introduces Vehicle as the name of a new category. Car, Motorcycle, and Truck are existing type names. They are called the member types of the category. The type names in a category specification may be language defined types or user defined types. In this example, we assume that they are descriptor types.
Operations may be defined for the members belonging to a category. For example, from a Vehicle we assume that its weight and the name and address of its owner may be requested. We may specify that as usual:
Weight(Vehicle) -> optional (Weight); Owner (Vehicle) -> optional (Owner);
In this example, both operations are accessor operations. Also mutator operations are allowed. However, no constructor operations can be defined for categories.
We use in both examples the optional quantifier for the results. This is required if we want to use a category as a member of another category as will be discussed in Section 14.5, "Categories of Categories".
A category is defined by a component. For example, the Vehicles component may be defined as (see Figure 14-1).
component Vehicles; type Vehicle = category (Car, Motorcycle, Truck); Weight (Vehicle) -> optional (Weight); Owner (Vehicle) -> optional (Owner); begin Weight (Car: C) = Weight (C); Weight (Motorcycle: M) = Weight (M); Weight (Truck: T) = Weight (T);Owner (Car: C) = Owner (C); Owner (Motorcycle: M) = Proprietor (M); Owner (Truck: T) = Holder (T); end component Vehicles;
Figure 14-1: Example of a category component.
Each operation defined for a category will be split into definition rules for the constituent types. The definition rules are using type matching to select the proper type and to call the corresponding definition of the selected type. In this example, it is assumed that the Weight operations are also defined for the Car, Motorcycle, and Truck classes. For the Owner operation it is assumed that the corresponding operations are Owner, Proprietor, and Holder depending on the class.
Categories may be specified in all situations where types are allowed. For example, they may be used in type-expressions, as input and output for operations and definitions, and as elements of arrays, lists, descriptors, and terms.
Often there is a need to convert the type of an entity into another type. For example, suppose we have a car, called MyCar, which we want to consider as a vehicle. In such a case we may use the following type-conversion expression:
While MyCar has the type of Car, the effect of this type-conversion is that the resulting value is of the category type Vehicle instead of the Car type. In the following name-definition:
are MyVehicle and MyCar both representing the same car, but MyVehicle has the type Vehicle while MyCar has the type Car.
The conversion from Car to Vehicle is allowed because Car is belonging to the category of Vehicle.
Another form of type-conversion, from category to member class, is also allowed as shown in the following example:
In this example is MyVehicle of type Vehicle. It will be converted to Car, if and only if MyVehicle represents a Car. It is an error if that is not the case.
As discussed earlier, the elements of heterogeneous collections may be of different types. With the concept of categories we are now able to define heterogeneous collections more accurately. We define a heterogeneous collection as a collection whose members are all belonging to the same category.
As an example, let use assume that we want to build a heterogeneous collection of Vehicles. Let C1 and C2 be the names of two cars, M1 the name of a motorcycle and T1, T2, and T3 the names of three trucks. Then we may define a heterogeneous list of vehicles in the following way:
As a general rule, the type of the first element of a list determines the types of all other elements. Where possible and necessary, automatic type-conversions will be performed for these elements. In this example, the type of the first element is Vehicle; all other elements are also converted to type Vehicle. The resulting list will be a heterogeneous list of type list(Vehicle).
We may now ask for the weight of all the vehicles in the following way:
This query will return for each vehicle in the list its weight, thereby making use of the Weight operation defined on category Vehicle.
Categories may also belong to other categories. Let us use, as an example, categories which represent different means of transportation as illustrated by Figure 14-2.
Conveyer | -------------------------------------------------- | | | Vehicle Vessel Aircraft | | | -------------------- ----------------- ------------------ | | | | | | | Car Motorcycle Truck Boat Ship Airplane Helicopter
Figure 14-2: Means of Transportation
Based on this hierarchy we may define the following categories for the lowest levels:
type Vehicle = category (Car, Motorcycle, Truck);type Vessel = category (Boat, Ship);type Aircraft = category (Airplane, Helicopter);
The categories for Vessel and Aircraft are similar to the Vehicle category we discussed earlier. We will assume that for the three categories the accessor operations of Weight and Owner are defined.
Similarly, we may also define categories for higher levels, such as:
type Conveyer = category (Vehicle, Vessel, Aircraft);
In this example Conveyer is a category based on other categories. This is in contrast with our previous examples where a category, such as Vehicle, is based on classes. ( In Elisa a class is represented by a (descriptor) type). Because of this difference the definitions for operations for categories based on other categories are also different. For example, the Conveyers component may be defined as in Figure 14-3.
component Conveyers; type Conveyer = category (Vehicle, Vessel, Aircraft); Weight (Conveyer) -> optional (Weight); Owner (Conveyer) -> optional (Owner); begin Weight(C) = (Weight(Vehicle:C), Weight(Vessel:C), Weight(Aircraft:C)); Owner(C) = (Owner(Vehicle:C), Owner(Vessel:C), Owner(Aircraft:C)); end component Conveyers;
Figure 14-3: Example of a category of categories component.
As shown by this example, each operation defined for a category which is based on other categories is defined by only one definition rule. The right-hand side of such a definition rule consists of a serial-expression which represents a list of alternatives, one for each member category. Each expression within the serial-expression is a call to the corresponding category operation.
Because the serial-expression is used in a definition which has the optional quantifier, the serial expression represents a list of alternatives, where only one alternative can be satisfied. That means that if, for instance, the Weight of a Conveyer should be determined, the definition first assumes that the Conveyer may be a Vehicle. If the called Weight definition of the Vehicles component confirms that, then the corresponding Weight value will be returned. If the Conveyer is not a Vehicle, the definition assumes that the Conveyer may be a Vessel, and so on.
A member of a category may also belong to other categories. That means that a class or a category may belong to more than one category.
Let us extend our example of Figure 14-2 with the concept of a seaplane as another means of transportation. A seaplane is an aircraft, but has also some properties of a vessel, as illustrated by Figure 14-4.
Based on these relationships we may redefine the following categories for the lowest levels:
type Vehicle = category (Car, Motorcycle, Truck);type Vessel = category (Boat, Ship, Seaplane);type Aircraft = category (Seaplane, Airplane, Helicopter);
The categories for Vessel and Aircraft have the Seaplane in common.
Because the Conveyer category represents a higher level of abstraction it is not affected by this change. The serial-expressions in the operation definitions are using the lower level category operations which are selecting only one of the possible overlapping alternatives.
Make a component for this category.
<!-- Start of StatCounter Code for Default Guide -->
var scJsHost = (("https:" == document.location.protocol) ?
"https://secure." : "http://www.");
<noscript><div class="statcounter"><a title="Web Analytics Made Easy -
StatCounter" href="http://statcounter.com/" target="_blank"><img
alt="Web Analytics Made Easy - StatCounter"></a></div></noscript>
<!-- End of StatCounter Code for Default Guide -->