Interactive
Software Engineering
Genericity and Inheritance

[ISE Home] Home ] Release Notes ] Technology Papers ] Installation Notes ] About Eiffel ]


10 COMBINING GENERICITY AND INHERITANCE

Genericity and inheritance, the two fundamental mechanisms for generalizing classes, may be combined in two fruitful ways.

The first technique yields polymorphic data structures. Assume that in the generic class LIST [G] the insertion procedure put has a formal argument of type G, representing the element to be inserted. Then with a declaration such as

    pl: LIST [POLYGON]

the type rules imply that in a call pl.put ("...") the argument may be not just of type POLYGON, but also of type RECTANGLE (an heir of POLYGON) or any other type conforming to POLYGON through inheritance.

The conformance requirement used here is the inheritance-based type compatibility rule; in simple cases, V conforms to T if and only if V is a descendant of T.

Structures such as pl may contain objects of different types, hence the name "polymorphic data structure". Such polymorphism is, again, made safe by the type rules: by choosing an actual generic parameter (POLYGON in the example) based higher or lower in the inheritance graph, you extend or restrict the permissible types of objects in pl. A fully general list would be declared as

    LIST [ANY]

where ANY, a Kernel Library class, is automatically an ancestor of any class that you may write.

The other mechanism for combining genericity and inheritance is constrained genericity. By indicating a class name after a formal generic parameter, as in

    VECTOR [T -> ADDABLE]

you express that only descendants of that class (here ADDABLE) may be used as the corresponding actual generic parameters. This makes it possible to use the corresponding operations. Here, for example, class VECTOR may define a routine infix "+" for adding vectors, based on the corresponding routine from ADDABLE for adding vector elements. Then by making VECTOR itself inherit from ADDABLE, you ensure that it satisfies its own generic constraint and enable the definition of types such as VECTOR [VECTOR [T]].

As you have perhaps guessed, unconstrained genericity, as in LIST [G], may be viewed as an abbreviation for genericity constrained by ANY, as in

     
    LIST [G -> ANY].