This site contains older material on Eiffel. For the main Eiffel page, see http://www.eiffel.com.

Generic creation

This technical note describes the mechanism for creating objects of formal generic types, as present in ISE Eiffel release 4.3. With the exception of an added Overview (section 1 below), it is identical to the text of a language extension proposal submitted by ISE to the Nonprofit International Consortium for Eiffel (NICE).

Note that the examples use the new syntax for creation instructions

    create x.make (...)

which is intended to replace the classical create x. Both forms will continue to be supported for several years.

All page numbers refer to the current definition of Eiffel: the book Eiffel: The Language.

1. Overview

The problem addressed by this extension is simple: how to create an object of a type known only through a formal generic parameters. In a class C [G], you may have declared x of type G, and want to execute a creation instruction

    create x.make (...)

for some creation procedure make of your choice.

For this to be type-safe, however, we need to know a little more about G, since in the most general case it represents an arbitrary type, so we have no clue about what kind of creation procedure it may require if any, and with what arguments. For this reason such creation instructions have been prohibited in Eiffel until now. You had to encapsulate the creation in a procedure on the client side (where the actual generic parameter is known -- separately for each client).

The new mechanism removes this limitation, due to the following elegant idea (credit for which is entirely due to Mark Howard from Axa Rosenberg, formerly Rosenberg Institutional Equity Management). It is based on the Eiffel technique of constrained genericity. To guarantee that the above creation instruction is valid, just make sure that G is a constrained generic parameter, with a class declaration of the form

    class C [G -> CONSTRAINT create make, ... end] ...

listing make as one of the applicable creation procedures. The rules are that

    make must be a procedure of the constraining type, CONSTRAINT, with of course the right argument types.

    When you use a generic derivation C [T], where type T must conform to CONSTRAINT, the version of make in T (possibly renamed, redefined etc.) must be listed as a creation procedure for T.

This ensures type safety.

The beauty of the scheme is that make, or any of the other creation procedures used for entities of type G, does not need to be a creation procedure in CONSTRAINT; it simply needs to be a procedure with the appropriate arguments. Only for descendants of CONSTRAINT used as actual generic parameters does it matter that make be a creation procedure.

This allows in particular CONSTRAINT to be a deferred class.

This overview should be sufficient to any Eiffel user desiring to use the mechanism. The detailed specification follows.

2. Syntax

The production for Constraint, on page 201, which reads
    
    Constraint == "->" Class_type
    
    
becomes
    
    Constraint == "->" Class_type [Creation_constraint]
    
    
with (see page 285)
    Creation_constraint == create Feature_list end
Note: in the syntax for Creators, page 285, the keyword creation will be replaced by create for simplicity. (The older keyword will continue to be accepted by compilers.)

3. Validity

New validity rule VTCC, page 201:

    A Constraint is valid if and only if every identifier listed in the Feature_list of its Generic_creators, if any, is the name of a procedure of the base class of its Creator_type.

Adaptation of VTCG, page 203 (with clause 3 already adapted for the "Generics in Constraints" change) now reads:

    Let C be a constrained generic class. A Class_type CT having C as base class is valid if and only if CT satisfies the Unconstrained Genericity rule (VTUG, page 201) and in addition, for any Formal_generic parameter G in the declaration of C having a constraint, then if D is the Class_type listed in the constraint and T, with base class BT, is the Type corresponding to G in the Actual_generics list of CT:

      3. T conforms to the type obtained from D by substituting any occurrence of a formal generic parameter of C by the corresponding actual parameter.

      4. If the constraint for G has a Generic_creators part, then the C version of every procedure of BT listed (as per rule VTCC, page 201) in that part is declared in BT as a creation procedure.

In VGCC, page 286, replace clause 1 by

    If T is a Formal_generic_name (that is to say, a formal parameter of the class where the instruction appears), then the corresponding formal generic parameter has a Constraint part with a Generic_creators part, and the creation instruction has a Creators part whose feature is one of the procedures listed (as per rule VTCC, page 201) listed in the Generic_creators part. Cases 2 to 6 assume that T is not a Formal_generic_name.

4. Semantics

The semantics of a creation call of the form
    create x.proc (arguments)
    
where the type of x is (as per VGCC (1)) a formal generic parameter with a constraint listing proc in its Generic_creators part, is to create an object of the type T used as the corresponding actual generic ■arameter in the generic derivation considered, using as creation procedure the version of proc in the base class BT of T. As per VGCC (3), BT must declare that version as a creation procedure.