Extensional Versus Intentional Interfaces

Another issue that can affect the compatibility of two components is the manner in which their interface requirements are expressed. There is a difference between extensionally and intensionally expressing interface requirements [Lat89]. Items that satisfy extensional requirements are typically defined by inclusion in a specified (possibly infinite) set of items. Items that satisfy intensional requirements, on the other hand, are defined by characteristic properties they must possess.

One example of an extensional interface requirement often appears in object-oriented languages: parameters must belong to a specific class. While classes can usually be extended via specialization, the conformance to an interface specification is determined by name equivalence to the parameter's class.

An example of an intensional interface requirement is a generic parameter to an Ada package. Here, conformance to the interface specification is determined by structural equivalence. For example, if a private type parameter is required, any Ada type that has the same properties as a private type—the presence of built-in equality and assignment operators, and so on—will conform to the interface.

More flexible intensional interface mechanisms are present in LIL [Gog84,Gog86,Tra90]. LIL supports formally defined correspondences between packages. As a result, when packages are used as generic parameters, any other package that can be shown to provide a conforming set of operations and types can be used to satisfy the interface requirements. With the addition of formal semantic definitions as in LILEANNA [Tra90], the structural equivalence can be extended to semantic equivalence.

Clearly extensional requirements are more limiting than intensional ones. The correspondence facilities present in languages like LIL allow one the freedom to express interface requirements in one way, but still meet those requirements with any component that provides the correct abstraction. While the restrictiveness of extensional interface requirements in an object-oriented programming language initially seems inconsequential, relieving it can create more problems. The use of multiple inheritance can arbitrarily broaden extensional requirements; however, using a single inheritance hierarchy for many purposes is fraught with difficulty [LaL89].

Also, generic parameters can be extensional. The RESOLVE programming language allows packages as generic parameters, but uses name equivalence rather than structural equivalence to determine conformance [Heg89]. As a result, a mechanism that on the surface appears very much like Ada's generic mechanism actually gives rise to extensional rather than intensional behavior.

The restrictive nature of extensional requirements specifications simply inflames the composability problem. It further restricts, or even overspecifies, the interface requirements so that even components with potentially compatible models of behavior cannot be combined.