330 likes | 449 Views
Lecture 18: Behavioral Subtyping and Eiffel . Must it be assumed that because we are engineers beauty is not our concern, and that while we make our constructions robust and durable we do not also strive to make them elegant?
E N D
Lecture 18: Behavioral Subtyping and Eiffel Must it be assumed that because we are engineers beauty is not our concern, and that while we make our constructions robust and durable we do not also strive to make them elegant? Is it not true that the genuine conditions of strength always comply with the secret conditions of harmony? Gustav Eiffel David Evans http://www.cs.virginia.edu/~evans CS655: Programming Languages University of Virginia Computer Science
Menu • Behavioral Subtyping Recap and Example • Eiffel’s Type System • Method overriding in C++ CS 655: Lecture 18
Subtype Definition (ST) • Subtype methods preserve the supertype methods’ behavior: • Signatures have contravariant arguments, covariant results • Pre-conditions of T imply preconditions of S; post-conditions of S imply post-conditions of T. • Subtypes preserve supertype properties • Invariant of S implies invariant of T. • Constraint of S implies constraint of T. CS 655: Lecture 18
Subtype Relation 2: Preserves supertype Properties • Subtypes preserve supertype properties For all states p and q such that p precedes q, for all x: S: Invariant Rule ISIT [ A (xp) / xp] Constraint Rule CSCT [A (xp) / xp, A (xq) / xq ] “covariance – subtype is stronger” CS 655: Lecture 18
Example • Liskov & Wing showed stack bag • Is bset bag? • bset specification on the Manifest • bag in Liskov & Wing, Figure 1 CS 655: Lecture 18
bset = type uses BSet (set for S) for all s: bset invariant max(sp.elements) <= sp.limit, min (sp.elements) >= 0. constraintsp.limit = sq.limit insert = proc (i: int) requires i <= sp.limit i >= 0. modifies s ensures spost.limit = spre.limit spost.elements = spre.elements {i} CS 655: Lecture 18
contains = proc (el: int) returns (bool) ensures result = el s choose = proc () returns (int) requires spre.elements {} modifies s ensures spost.elements = spre.elements – { result } result spre.elements spost.limit = spre.limit size = proc() returns (int) ensures result = | s.elements | equal = proc (t: set) returns (bool) ensures result = (s = t) CS 655: Lecture 18
Subtype Definition (ST) • Subtype methods preserve the supertype methods’ behavior: • Signatures have contravariant arguments, covariant results • Pre-conditions of T imply preconditions of S; post-conditions of S imply post-conditions of T. • Subtypes preserve supertype properties • Invariant of S implies invariant of T. • Constraint of S implies constraint of T. CS 655: Lecture 18
Subtype Condition 1: Methods Rule • Methods rule: • Pre-condition x : s mT.pre [ A (xpre) / xpre ] mS.pre Replace every xpre in mT.pre with A(xpre). Abstraction function, A : s t. • Post-condition mS.post mT.post [A (xpre) / xpre, A (xpost) / xpost] “contravariance – subtype is weaker” “covariance – subtype is stronger” CS 655: Lecture 18
We need an Abstraction Function A type is: < set of objects, set of values, set of methods > bset = <Oset, BSet, { insert, contains, choose, size, equal } > bag = <Obag, BBag, { put, get, card, equal } > • We need an abstraction function that maps both to the same abstract type: A : BSet BBag BSet: < s.elems, s.limit > BBag: < s.elems, s.bound > • s : BSetA (s) = < s.elems, s.limit > • Renaming: R(insert) = put, R(choose) = get, R(size) = card, R(equal) = equal CS 655: Lecture 18
Check method choose get1. Preserves method behavior. • Signatures: get =proc () returns (int); choose = proc () returns (int) • Pre-condition of get pre-condition of choose x : BSet get.pre [ A(xpre) / xpre ] choose.pre bpre.elems {} [A(bpre) / bpre ] spre.elems {} • s : BSet; A (s) = < s.elements, s.limit > so we can replace bpre.elems with spre.elems and the implication holds. • Post-condition of choose post-condition of get • Can prove with similar renaming CS 655: Lecture 18
Check method insert put • Signatures: put =proc (i: int); insert = proc (i: int) • Pre-condition of put pre-condition of insert • x : BSet put.pre [ A(xpre) / xpre ] insert.pre | A(spre).elems | < A(spre).bound i <= sp.limit i >= 0 • NO! The subtype method has a stronger pre-condition, so it is not a subtype. CS 655: Lecture 18
Does this make sense? • Intuition: subtype is unsafe, if there is some program written for the supertype that can tell the difference • Here’s one: put (999235); insert (999235); CS 655: Lecture 18
uset bag? • A : S T • A : Set BBag • s : Set; A (s) = < s, > • Renaming: • R(insert) = put R(choose) = get • R(size) = card R(equal) = equal • Check method choose get (same as bset) 8 CS 655: Lecture 18
Check method insert put • Pre-condition of put pre-condition of insert • x : BSet put.pre [ A(xpre) / xpre ] insert.pre = true • Post-condition of insert post-condition of put insert.post put.post [ A(xpre) / xpre, A(xpost) / xpost] (spost.elements = spre.elements { i }) • (bpost.elems = bpre.elems { i } bpost.bound = bpre.bound) [ A(bpre) / bpre, A(bpost) / bpost] recall: A (s) = < s, infinity> so (spost.elems = spre.elems { i } infinity = infinity CS 655: Lecture 18
Check Invariant • Need to show: IS IT [ A(xp) / xp] true (| bp.elems | <= bp.bound) [ A(bp) / bp] true (| <s.elements, infinity>.elems | <= <s.elements, infinity>.bound true true • Similar for constraint • uset is a subtype of bag! Yippee! (Except: signature of equal should take a bag!) CS 655: Lecture 18
Summary Questions • uset bset?, bset uset? • Does the Liskov/Wing subtype relation definition match intuition? • Is it useful? CS 655: Lecture 18
Eiffel and I Can’t Get Up Eiffel’s Type System
Normal Procedure Type Rule f = proc(p1: P1, ..., pn: Pn) returns (X) g = proc(p1: Q1, ..., pn: Qn) returns (Y) Qi Pi forall i in 1..n X Y f g Procedures are contravariant on parameters, covariant on results. CS 655: Lecture 18
Eiffelling Athlete How can Girl override set_roomate? Covariance: set_roommate (Girl) set_roommate (Boy) Contravariance: set_roommate (Athlete) Novariance: set_roommate (Skier) (Eiffel) Skier set_roommate (Skier) (Sather) (C++ (complicated), Java) Boy Girl CS 655: Lecture 18
Can’t Get Up? Athlete s: skier; g: girl; b: boy; s := g; ... s.set_roommate (b); Skier set_roommate (Skier) Girl set_roomate (Girl) Boy CS 655: Lecture 18
Meyer’s Excuse Strangely enough, some workers in the field have been advocating a contravariant policy. Here it would mean that if we go for example to class RANKED_GIRL, where the result of roommate is naturally redefined to be of type RANKED_GIRL, we may for the argument of routine share use type GIRL, or rather scaringly, SKIER of the most general kind. One type that is never permitted in this case is RANKED_GIRL! Here is what, under various mathematical excuses, some professors have been promoting. No wonder teenage pregnancies are on the rise. CS 655: Lecture 18
What’s wrong with Meyer’s Rule? • Disallow polymorphic catcalls: s.f (t) where some subtype of type of s hides f or changes covariantly type of parameters of f. • Violates useful notion of subtyping: adding a new subtype breaks existing programs! • Eiffel compiler will complain for redefinition CS 655: Lecture 18
What does C++ really do? • Can add covariant methods in subtype, but they overload the original method, instead of overriding it! • Does this make sense? CS 655: Lecture 18
class skier { public: virtual void set_roommate (class skier *s) { fprintf (stderr, "skier roomate!"); } } ; class girl : public skier { void set_roommate (class girl *g) { fprintf (stderr, "girl roomate!"); } } ; class boy : public skier { void set_roommate (class boy *b) { fprintf (stderr, "boy roomate!"); } } ; int main (void) { girl *g = new girl (); boy *b = new boy (); skier *s; s = g; s->set_roommate (b); g->set_roommate (b); } CS 655: Lecture 18
Result • Both g++ and MSVC++ produce compile-time errors for g->set_roommate (b) skiers.C:27: no matching function for call to `girl::set_roommate (boy *&)' skiers.C:9: candidates are: void girl::set_roommate(girl *) • After removing this line, compiles okay, produces: “skier roomate!” (calls the superclass method) • If girl::set_roommate (girl *) overloads, but doesn’t override skier::set_roommate why does this happen? CS 655: Lecture 18
Some C++ Facts • 1996 Draft Standard is 680 pages long • 50x more complex than Algol60! Is this progress? • Current open issues list of Core Language Issues contains 223 issues • Compare to Knuth’s 9 ambiguities in Algol 60 • Current open issues list for standard library (Revision 12) is 59 pages • Good luck! CS 655: Lecture 18
Date: Fri, 03 Mar 2000 18:09:53 -0500 From: Avneesh Saxena <avneesh@cs.virginia.edu> To: bs@research.att.com Subject: C++: overriding problems! Sir, I am Avneesh, a graduate student in the CS Dept, Univ of Virginia. I am currently taking a course on Programming languages in which we are doing a detailed study of subclassing mechanisms in computer languages. I have learned C++ from your book "The C++ Pgm'ing Language" which is written in a very clear and concise manner. Especially, the concepts are made clear and ambiguties about language features have been discussed and resolved in an appreciable manner. However, I have run in a problem while trying to figure out what this code would do: CS 655: Lecture 18
... (example same as ours but less of a social statement) I have tried to run this code both through GCC v2.8.1 and MS-VC++, which give the same results. It appears that while we would accept other() to be accessible through the derived classes, the compiler doesn't find it. The second (more serious)problem is when other(bPtr) is called, we expect it to execute the function which has been defined in class B as it overrides the function defines in class A as the type of the actual argument matches this more closely; however, it executes the base classes function (circumvents polymorphism!). I tried to check if this behavior was consistent with the language definition but I failed to find anything which would clarify things. So, I am left wondering whether this is a case of the compiler not understanding the language and doing something wrong or is it what the language desires? I hope you will be able to clarify things for me, Thanks, Avs CS 655: Lecture 18
Subject: Re: C++: overriding problems! Date: Sat, 4 Mar 2000 20:19:34 -0500 (EST) From: Bjarne Stroustrup <bs@research.att.com> To: avneesh@cs.virginia.edu > ... (copy of Avneesh’s message elided) Your problem is that you think that the two other() function overloads. They don’t functions in different scope do not overload, so when you look at scope C::other(). If you want overloading you'll have to explicitly do so in C. One simple way of doing so is to say: using B::other; in C, but that's a relatively new feature > I have tried to run this code both through GCC v2.8.1 and MS-VC++, which give the same > results. It appear that while we would accept other() to be > accessible through the derived classes, the compiler doesn't find it. I think you mean "expect", but you expect wrongly. > ... So, I am left wondering whether this is a case of the compiler not understanding the > language and doing something wrong or is it what the language desires? The compilers are wrong I suggest a re-read of the sections about deriving classes in your textbook. CS 655: Lecture 18
Emailing Experts • All of you should (soon if not already) have email exchanges with experts relevant to your projects • One good email can save you reading thousands of pages! • Good to build your research contacts CS 655: Lecture 18
Be polite Introduce Yourself (be brief) Flattery is always a good idea! (okay to lie a little if necessary) Do your homework first Concisely ask a clear and specific question. Date: Fri, 03 Mar 2000 18:09:53 -0500 From: Avneesh Saxena <avneesh@cs.virginia.edu> To: bs@research.att.com Subject: C++: overriding problems! Sir, I am Avneesh, a graduate student in the CS Dept, Univ of Virginia. I am currently taking a course on Programming languages in which we are doing a detailed study of subclassing mechanisms in computer languages. I have learned C++ from your book "The C++ Pgm'ing Language" which is written in a very clear and concise manner. Especially, the concepts are made clear and ambiguties about language features have been discussed and resolved in an appreciable manner. However, I have run in a problem while trying to figure out what this code would do: CS 655: Lecture 18
Charge • Be ready for elevator speeches next week: • Convince the class your project is interesting and worthwhile in 90 seconds • Next time: pragmatic aspects of OO languages - comparison of Sather, Eiffel, Java and C++ CS 655: Lecture 18