db@lfcs.ed.ac.uk (Dave Berry) (03/09/90)
I've been re-reading an exchange about preconditions and multiple inheritance that took place in comp.lang.eiffel last year. The example under consideration was a class COMPANY_PLANE that inherited from PLANE and ASSET. The precondition for "fly" in PLANE was that the user should be a qualified pilot, the precondition for "use" in ASSET was that the user should be a company employee, and the resulting precondition for "fly" in COMPANY_PLANE was that the user should be both a qualified pilot and a company employee. The problem with this formulation is that it strengthens the precondition of "fly" in the subclass instead of weakening it. The response to this was that a well-designed PLANE class would allow for more specific qualifications, such as being allowed to fly the plane by its owner. Similarly, the ASSET class should allow for other qualifications than being an employee, because not all employees can use every asset. So either: 1. The class hierarchy should have been better designed in the first place. or 2. You should go back and redesign the class hierarchy. It seems to me that case 2 is against the spirit of other decisions made in the design of Eiffel. I say this because the two most controversial parts of the Eiffel type system, namely the covariant rule for types of the arguments of redefined functions and the orthogonality of inheritance and visibility, were expressly designed to handle cases when the inheritance hierarchy could not be redesigned. They are a recognition of the practical truth that we don't always have an ideal base to work from. By analogy, the "require" clause should make the same allowances. There may be times when we can't guarantee that the precondition of a redefined function will be weaker than that of the original. Eiffel shouldn't enforce contravariance for assertions if it doesn't enforce it for types. I can think of two possible approaches: 1. Make "require or" the normal way to specify preconditions of redefined routines, as at present, but to keep "require" as an option (or allow "require and" instead). 2. Insist on covariant assertions, by replacing "require or" with "require and". Presumably the restrictions that currently apply to redefined routines with argument types that are subtypes of the original would also apply to a redefined routine that used "require and". I admit that this seems an extreme point of view, but the covariance rule seemed strong when I first met it. Certainly the current situation, where one sort of precondition (argument types) is covariant and the other ("require" clause) is contravariant, seems inconsistent. Comments? Dave Berry, LFCS, Edinburgh Uni. db%lfcs.ed.ac.uk@nsfnet-relay.ac.uk "The thought of someone sharing one's own preferences without also sharing one's aversions strikes most people as utterly inconceivable." - C. A. Tripp.
db@lfcs.ed.ac.uk (Dave Berry) (03/21/90)
I'm posting this for Andreas Schramm (schramm%uucp.gmdtub@de.uni-dortmund.informatik.unido) because posting to Usenet is not implemented at his site. Dave Berry. ----------------------------------------------------------------------------- > ... Certainly the current situation, where > one sort of precondition (argument types) is covariant and the other > ("require" clause) is contravariant, seems inconsistent. > > Comments? According to Dr. Meyer, covariant redefinition of routine argument types is an indispensable feature. However, if routine argument types are seen as preconditions, their covariant redefinition violates the "programming as contracting" paradigm, which requires that preconditions must not be strengthened (contravariance). In order to reconcile the two conflicting requirements I propose: Make the extent to which argument type redefinitions in descendant classes are permitted part of the contract. Enforce that routine redefinitions are bound by the contract as it has been defined by the original top-most supplier of a routine. This appears tolerable since the original supplier should usually know in advance which argument type restrictions will make sense when subtypes are introduced. This assumption is justified because the original definition is supposed to fix the meaning of a routine and all its redefinitions, while redefinitions are supposed to be just specialized implementations [OOSC 10.1.10]. Note that it has never been a requirement that contracts are phrased in statically checkable terms. In fact, preconditions (which are part of a contract) often are not. Thus an appropriately phrased contract may e.g. tie routine argument types to the state space of the object involved, which amounts to covariant argument type redefinitions. Some time ago I wrote a letter to Dr. Meyer which contained a suggestion how to to embed this idea in Eiffel. The suggestion was: The top-most definition of a routine fixes its argument types _textually_ once and for all, i.e. for redefinitions the argument types have to be copied textually. The necessary flexibility is preserved because an argument type need not necessarily be a class type but may be of the form "like a" or may refer to a formal generic type parameter. This, by the way, requires the following modification of the rule above: Anchor renamings and instantiations of the parents' formal generic type parameters at inheritance time have to be taken into account. An argument declaration "x: A" would mean that the contract includes "Every redefinition shall accept an argument of type A". An argument declaration "x: like a" would mean that the contract includes "Every redefinition shall accept an argument of a dynamic type that conforms to the declared type of feature a in the class of the type of the object involved at run-time." The former phrase is static, the latter dynamic in nature. In order to imitate the original flexibility of argument type redefinitions, at worst an artificial anchor might have to be introduced; but it strikes me that covariant argument type redefinitions often refer to an already existing feature anyway. Andreas Schramm Dave Berry, LFCS, Edinburgh Uni. db%lfcs.ed.ac.uk@nsfnet-relay.ac.uk "Excuse me, Mr. Policeman, but someone seems to have stolen my soul. What're you going to do about that then, Officer?" -- Here and Now.