Example 3-3. Example:
abstract class $SHIPPING_CRATE{T} < $CONTAINER{T} is destination:$LOCATION; weight:FLT; end |
abstract_class_definition ==> abstract class abstract_class_name [ parameterization ] [ subtyping_clause ] [ supertyping_clause ] is [ abstract_signature ] { ; [ abstract_signature ] } end |
subtyping_clause ==>
< type_specifier_list |
supertyping_clause ==>
> type_specifier_list |
type_specifier_list ==>
type_specifier { , type_specifier} |
Abstract class definitions specify interfaces without implementations. Abstract class names must be entirely uppercase and must begin with a dollar sign '$' (See Sather identifiers are used to name class features, method arguments, and local variables. Most consist of letters, decimal digits, and the underscore character, and begin with a letter. Iterator names additionally end with the '!' character. Abstract type names and class names are similar, but the letters must be uppercase and abstract type names begin with '$'. There are no restrictions on the lengths of Sather identifiers or class names. Identifiers, class names, and keywords must be followed by a character other than a letter, decimal digit, or underscore. This may force the use of white-space after an identifier.); this makes it easy to distinguish abstract type specifications from other types, and may be thought of as a reminder that operations on objects of these types might be more expensive since they may involve dynamic dispatch. The scope of abstract type names is the entire program. Two abstract class definitions may be parameterized (see See Parameterization) and may have the same name only if they specify a different number of type parameters.
A subtyping clause ('<' followed by type specifiers) adds to the type graph an edge from each type in the type_specifier_list to the type being defined. In the example, the subtyping clause is '< $CONTAINER{T}'. Each listed type must be abstract. Every type is automatically a subtype of $OB (See Built-in classes). There must be no cycle of abstract types such that each appears in the subtype list of the next, ignoring the values of any type parameters but not their number. A subtyping clause may not refer to 'SAME'.
A supertyping clause ('>' followed by type specifiers) adds to the type graph an edge from the type being defined to each type in the type_specifier_list. These type specifiers may not be type parameters (though they may include type parameters as components) or external types. There must be no cycle of abstract classes such that each class appears in the supertype list of the next, ignoring the values of any type parameters but not their number. A supertyping clause may not refer to 'SAME'.
If both subtyping and supertyping clauses are present, then each type in the supertyping list must be a subtype of each type in the subtyping list using only edges introduced by subtyping clauses. This ensures that the subtype relationship can be tested by examining only definitions reachable from the two types in question, and that errors of supertyping are localized.
The body of an abstract class definition consists of a semicolon separated list of abstract signatures. Each specifies the signature of a method without providing an implementation at that point. The argument names are required for documentation purposes only and are ignored. The abstract signatures of all types listed in the subtyping clause are included in the interface of the type being defined. Explicitly specified signatures override any conflicting signatures from the subtyping clause. If two types in the subtyping clause have conflicting signatures that are not equal, then the type definition must explicitly specify a signature that overrides them. The interface of an abstract type consists of any explicitly specified signatures along with those introduced by the subtyping clause.
Example 3-4. Here's an example from the standard library. The abstract class '$STR' represents the set of types that have a way to construct a string suitable for output. All of the standard types such as 'INT', 'FLT', 'BOOL' and 'CPX' know how to do this, so they are subtypes of '$STR'. Attempting to subtype from '$STR' a concrete class that didn't provide a 'str' method would cause an error at compile time.
abstract class $STR is -- Subtypes of this define "str:STR". -- This should be a reasonable -- string representation of an object. str:STR; -- String form of object. end |
Example 3-5. Here's another abstract class that subtypes from '$STR'. In addition to requiring the 'str' method, it adds a 'create' method for creating from the string representation.
abstract class $FROM_STR < $STR is -- Subtypes of this must define -- methods for going to and from -- the STR representation. create(s:STR):$FROM_STR; end |
Example 3-6. In this illegal abstract class, A and B do not conflict because their arguments are concrete and are not the same type. However, because the argument of C is abstract and unrelated it conflicts with both A and B. D does not conflict with A, B or C because it has a different number of parameters.
abstract class $FOO is foo(arg:INT); -- method A foo(arg:BOOL); -- method B foo(arg:$FOO); -- method C foo(a, b:INT); -- method D end; |