An enumerated type defines a fixed set of values which are distinguished through a unique name.
Enumerated types are used whenever an object's value at runtime is a named value among a defined set of possible named values. For example:
enumerated type size defines the following possible named values: small, medium and large.
enumerated type quality defines the following possible named values: very_bad, bad, standard, good, and very_good.
Enumerated types are governed by the following rules:
The name of an enumerated value consists of a prefixed identifier starting with en_ as prefix.
As for all prefixed identifiers, writing the prefix in source code is optional, as long as there is no ambiguity detected by the compiler. Hence, writing small is equivalent to writing en_small.
The syntax to define an enumerated type is as follows:
Table 11.1. Enumerated type
| Production | Syntax | Links |
|---|---|---|
enumerated_type |
| Chapter 11, Enumerated type |
Example:
type SML_size enumerated small; medium; large end end
No factory needs to be created for an enumerated type.
A unique object for each value of each enumerated type is automatically created at runtime.
If the type of an object reference (attribute, input argument, output argument, constant or variable) is an enumerated type, then the syntax used to declare the object reference's type is: enumerated_type_identifier.enumerated, and a value of an enumerated type is accessed with the syntax enumerated_type_identifier.enumerated_value_identifier.
Example:
service enumerated_examples
command example_1
script
// declare variable 'size' of enumerated type 'SML_size'
var SML_size.enumerated size
// assign value 'large' to variable 'size'
size = SML_size.large
// same instruction with prefixed identifiers:
v_size = ty_SML_size.en_large
end
end
endAll objects of an enumerated type are themselves instances of type enumerated.
Type enumerated is defined as follows:
type enumerated inherit !extended_comparable<other:enumerated; min_max_result:enumerated> end inherit hashable end attribute a_id type:enumerated_id end attribute a_index type:positive32 end end type
It follows from the above type definition that:
two enumerated values can be compared (equal, greater than, less than), because type enumerated inherits from type extended_comparable. The magnitude of each value is determined through the order in which the values appear in the declaring type. Each value has a higher magnitude than its preceding value.
objects of type enumerated can be used for keys in maps, because type enumerated inherits from type hashable.
attribute id provides the prefixed identifier for an enumerated value.
attribute index provides a numeric integer value that is assigned to each enumerated value. The first enumerated value appearing in the declaring type starts with index 1, and the index is then incremented by one for each subsequent value.
Enumerated types are compile-time and run-time type-safe.
For example, suppose that:
enumerated type size defines the values small, medium and large.
enumerated type quality defines the values bad, medium and good.
In that case, an object of type size.enumerated cannot be assigned to an object of type quality.enumerated, and vice versa. Moreover, the values medium of type size and medium of type quality are semantically different, and thus incompatible, although their identifiers and indexes are the same.
In some programming languages it is common to define enumerated values with integer or string constants.
An example of using integers in C is:
typedef enum {SMALL, MEDIUM, LARGE} size;And an example of using strings in Java is shown below. (Note that Java also provides type-safe enum values since version 1.5)
public class Quality {
public static final String BAD = "bad";
public static final String STANDARD = "standard";
public static final String GOOD = "good";
}The above way of defining enumerated values always have a severe drawback: there is no type safety. This opens the door for many possible programming errors which can be difficult to detect, because the effect of a semantically incompatible value assigned to an enumerated object might be detected long after the wrong assignment took place. Therefore, the above way to work with enumerated values should never be used in Obix. Instead, an enumerated type should be used, in order to ensure compile-time and run-time type safety.
Suppose the following type has been defined:
type SML_size enumerated small; medium; large end end
For each one of the above defined enumerated values, the following table shows the two attribute values of type enumerated:
Table 11.2. Attribute values of enumerated values
| Enumerated value | Value of attribute id | Value of attribute index |
|---|---|---|
small | en_small | 1 |
medium | en_medium | 2 |
large | en_large | 3 |
The following code demonstrates the rules explained above:
service enumerated_examples
command example_2
script
// declare and initialize some variables
var SML_size.enumerated size_small = SML_size.small
var SML_size.enumerated size_medium = SML_size.medium
var SML_size.enumerated size_large = SML_size.large
var SML_size.enumerated size_earth = SML_size.large
// check attribute 'id' of type 'enumerated'
check script size_small.id.to_string =v "en_small"
check script size_small.id.suffix.to_string =v "small"
check script size_earth.id.to_string =v "en_large"
// check attribute 'index' of type 'enumerated'
check script size_small.index =v 1
check script size_medium.index =v 2
check script size_large.index =v 3
check script size_earth.index =v 3
// compare values
// greater than
check script size_medium > size_small
check script size_large > size_medium
// less than
check script size_small < size_large
// equal
check script size_large =v size_earth // compare values
check script size_large =r size_earth // compare references
// unequal
check script size_small #v size_large // compare values
check script size_small #r size_large // compare references
end
end
end