[Next] [Previous] [Up] [Top] [Contents] [Index]

3.3 Type and Signature Declarations

3.3.2 Representation and Object Declarations

New user-defined objects are introduced with representation declarations of the following form (again, ignoring parameterization and encapsulation):

object_decl 	::=	rep_role rep_kind name {relation} [field_inits] ";"
rep_kind	::=	"representation"	declares an object implementation
	|	"object"	declares an object type and implementation
relation	::=	"subtypes" types	impl conforms to type, type subtypes from type
	|	"inherits" parents	impl inherits from impl
	|	"isa" parents	impl inherits from impl, type subtypes from type

Representation roles will be described in section 3.5.

If the representation keyword is used, the declaration introduces a new object representation. This object inherits from the objects named in each inherits clause and conforms to the types named in each subtypes clause. As mentioned in section 2.1.1, the inheritance graph cannot have cycles.

An isa clause is syntactic sugar for both a subtypes clause and an inherits clause, i.e., sugar for the case where inheritance and subtyping are parallel. So the following declaration

representation cons isa list;

is syntactic sugar for the declaration

representation cons inherits list subtypes typeof(list);

where typeof(list) represents the most-specific type(s) to which the list object conforms (typeof is not legal Cecil syntax).

If the object keyword is used, then the declaration is syntactic sugar for the pair of an object representation declaration and a type declaration. A declaration of the form

object name 				inherits namei1, namei2, ..., namein
				subtypes names1, names2, ..., namesm
				isa nameb1, nameb2, ..., namebk ;

is syntactic sugar for the following two declarations:

type name 				subtypes names1, names2, ..., namesm,
							typeof(nameb1), typeof(nameb2), ..., typeof(namebk) ;
representation name
				inherits namei1, namei2, ..., namein, nameb1, nameb2, ..., namebk
				subtypes name ;

Both the object and the type have the same name, but there is no potential for ambiguity since object and type names are resolved in separate name spaces. The new type subtypes from all the types listed in the subtypes clause and from the types to which the objects in the isa clause of the original declaration conform. The new object representation conforms to the new type and inherits from the object representations listed in the inherits and isa clauses of the original declaration.

The object and isa syntactic sugars are designed to make it easy to specify the inheritance and subtyping properties of an object/type pair for the common case that code inheritance and subtyping are parallel. We expect that in most programs, only object and isa declarations will be used; type, representation, inherits, and subtypes declarations are intended for relatively rare cases where finer control over inheritance and subtyping are required.

Object constructor expressions are similarly extended with representation roles, representation kinds, and subtyping relationships:

object_expr 	::=	rep_role rep_kind {relation} [field_inits]

In an object constructor expression, both the representation keyword and the object keyword have the same effect; the presence or absence of an anonymous type is immaterial.

Representations often add new, implementation-specific operations. For example, the cons representation defined earlier introduced the head and tail fields. To be able to send messages that access these new features, a type must exist that includes the appropriate signatures. If cons were only a representation, then a separate type would need to be defined that included signatures for head and tail. To avoid this extra step, a representation declaration, like an object declaration, introduces a corresponding type. Unlike an object declaration, however, the type derived from a representation declaration is anonymous. It can only be referenced indirectly through the typeof internal function that specifies the semantics of the isa and @: syntactic sugars (section 3.3.5 describes the @: sugar). Consequently, no variables or unspecialized formals may be declared to be of the anonymous type, and no types may be declared to be subtypes of the anonymous type. This enables object representations to be defined that are not treated as first-class types; the programmer has control over which types are intended to be used in type declarations.