$17.3 COVARIANCE AND DESCENDANT HIDING 621 the typing question is when to ascertain that there will be a feature lower landing gear applicable to the object(for a COPTER there would not be any);the binding question is which version to choose (since we have several versions,as shown). Static binding would mean that we disregard the object type and believe the entity declaration,leading us for example to apply to a Boeing 747-400 the version of a feature, such as lower landing gear,that has been defined for the standard Boeing 747 planes, instead of the version specially redefined for the 747-400 variant;this is clearly wrong if the object is of the latter type.Dynamic binding will apply the operation that the object demands,based on its type;this is the right approach. With static typing we will refuse the call at compile time unless we can guarantee that whatever happens to myaircraft at run time the type of the attached object will be equipped with a feature corresponding to lower landing gear.The basic technique for obtaining this guarantee is simple:since we must declare my aircrafi,we require that its type's base class include such a feature.This means that the declared type cannot be AIRCRAFT since there is no lower landing gear at that level;helicopters,for example, have no landing gears,for the purpose ofthis example at least.With such a declaration the compiler would reject our software with no possibility of appeal.But if we declare the entity as being of type PLANE,which has the required feature,all is well. Smalltalk-style ynamic typing would mean waiting until execution to find out if there is an applicable feature;acceptable perhaps for prototypes and experimental software,but not for production systems.Run time is a little late to ask whether you have a landing gear. IZ3 COVARIANCE AND DESCENDANT HIDING In a simple world a discussion of typing would stop here:we have defined the goals and advantages of static typing;examined the constraints that a realistic type system must meet;and reviewed the typing techniques of the object-oriented framework developed in the preceding chapters,checking that they satisfy the stated criteria. The world is not simple.The com bination of static typing with some of the software engineering requirements of object technology makes the issues more difficult than they appear at first.Two techniques raise difficulties:covariance,the change ofargument types in redefinitions;and descendant hiding,the ability for a class to restrict the export status of an inherited feature. Covariance See the original discussions in "TYPINGAND The principal problem is what happens to arguments when we redefine a feature's type. REDECLARATION"We have encountered several cases already:devices and printers,linkable and bi-linkable ,16.6page596a1a elements,points and their conjugates. “ANCHORED DECLARATION” To understand the general nature of the issue let us use a fresh example.Being non- 16.7,page599. technical,it carries the usual risks of metaphors;but the closeness to software schemes is obvious,and we will frequently come back to actual software examples
§17.3 COVARIANCE AND DESCENDANT HIDING 621 the typing question is when to ascertain that there will be a feature lower_ landing_gear applicable to the object (for a COPTER there would not be any); the binding question is which version to choose (since we have several versions, as shown). Static binding would mean that we disregard the object type and believe the entity declaration, leading us for example to apply to a Boeing 747-400 the version of a feature, such as lower_landing_gear, that has been defined for the standard Boeing 747 planes, instead of the version specially redefined for the 747-400 variant; this is clearly wrong if the object is of the latter type. Dynamic binding will apply the operation that the object demands, based on its type; this is the right approach. With static typing we will refuse the call at compile time unless we can guarantee that whatever happens to my_aircraft at run time the type of the attached object will be equipped with a feature corresponding to lower_landing_gear. The basic technique for obtaining this guarantee is simple: since we must declare my_aircraft, we require that its type’s base class include such a feature. This means that the declared type cannot be AIRCRAFT since there is no lower_landing_gear at that level; helicopters, for example, have no landing gears, for the purpose of this example at least. With such a declaration the compiler would reject our software with no possibility of appeal. But if we declare the entity as being of type PLANE, which has the required feature, all is well. Smalltalk-style ynamic typing would mean waiting until execution to find out if there is an applicable feature; acceptable perhaps for prototypes and experimental software, but not for production systems. Run time is a little late to ask whether you have a landing gear. 17.3 COVARIANCE AND DESCENDANT HIDING In a simple world a discussion of typing would stop here: we have defined the goals and advantages of static typing; examined the constraints that a realistic type system must meet; and reviewed the typing techniques of the object-oriented framework developed in the preceding chapters, checking that they satisfy the stated criteria. The world is not simple. The combination of static typing with some of the software engineering requirements of object technology makes the issues more difficult than they appear at first. Two techniques raise difficulties: covariance, the change of argument types in redefinitions; and descendant hiding, the ability for a class to restrict the export status of an inherited feature. Covariance The principal problem is what happens to arguments when we redefine a feature’s type. We have encountered several cases already: devices and printers, linkable and bi-linkable elements, points and their conjugates. To understand the general nature of the issue let us use a fresh example. Being nontechnical, it carries the usual risks of metaphors; but the closeness to software schemes is obvious, and we will frequently come back to actual software examples. See the original discussions in “TYPING AND REDECLARATION” , 16.6, page 596 and “ANCHORED DECLARATION”, 16.7, page 599
622 TYPING $17.3 The example involves a high-school ski team preparing for a trip to a minor-league championship,and the team members'concerned parents.For brevity and simplicity it uses the class names GIRL as an abbreviation for"member of the girls'ski team"and BOY as an abbreviation for "member of the boys'ski team".Some skiers on each team are ranked,that is to say have already recorded good results in earlier championships.This is an important notion:ranked skiers will start first in a slalom,thus gaining a considerable advantage over the others since a slalom run is much harder to negotiate after too many competitors have already worked it.(This rule that ranked skiers go first is a way to privilege the already privileged,and may be the reason why skiing exerts such a fascination over many people:that it serves as an apt metaphor for life itself.)We get two new classes,RANKED GIRL and RANKED BOY. Kinds ofskier SKIER GIRL BOY RANKED GIRL RANKED BOY Some rooms are reserved for boys only,girls only,ranked girls only;we may use a class hierarchy parallel to the one above:ROOM,GIRL ROOM,RANKED GIRL ROOM etc.The discussion will omit RANKED BOY which is parallel to RANKED GIRL. Here is an outline of class SK/ER: class SKIER feature roommate:SKIER --This skier's roommate share (other:SKIER)is --Choose other as roommate. require other Void do roommate :other end ..Other possible features omitted in this class and the following ones... end -class SK/ER We have two features of interest:the attribute roommate;and the procedure share, which assigns a certain skier as roommate to the current skier,as in
622 TYPING §17.3 The example involves a high-school ski team preparing for a trip to a minor-league championship, and the team members’ concerned parents. For brevity and simplicity it uses the class names GIRL as an abbreviation for “member of the girls’ ski team” and BOY as an abbreviation for “member of the boys’ ski team”. Some skiers on each team are ranked, that is to say have already recorded good results in earlier championships. This is an important notion: ranked skiers will start first in a slalom, thus gaining a considerable advantage over the others since a slalom run is much harder to negotiate after too many competitors have already worked it. (This rule that ranked skiers go first is a way to privilege the already privileged, and may be the reason why skiing exerts such a fascination over many people: that it serves as an apt metaphor for life itself.) We get two new classes, RANKED_GIRL and RANKED_BOY. Some rooms are reserved for boys only, girls only, ranked girls only; we may use a class hierarchy parallel to the one above: ROOM, GIRL_ROOM, RANKED_GIRL_ROOM etc. The discussion will omit RANKED_BOY which is parallel to RANKED_GIRL. Here is an outline of class SKIER: class SKIER feature roommate: SKIER -- This skier’s roommate share (other: SKIER) is -- Choose other as roommate. require other /= Void do roommate := other end … Other possible features omitted in this class and the following ones … end -- class SKIER We have two features of interest: the attribute roommate; and the procedure share, which assigns a certain skier as roommate to the current skier, as in Kinds of skier BOY SKIER GIRL RANKED_GIRL RANKED_BOY