object-oriented software construction bertrand meyer lesson...
TRANSCRIPT
Chair of SoftwareEngineering
Object-Oriented Software ConstructionBertrand Meyer
Lesson 21
Last update: 25 May 2004
Type issues, covariance and catcalls
Programming in the Large, 20042 Chair of SoftwareEngineering
What’s special about this lecture
Mix of:
Fundamental concepts Unsolved issues Recent proposal
Programming in the Large, 20043 Chair of SoftwareEngineering
Flexibility vs. safety
Expressive power (no “bondage and discipline” language)
Protection against crashes and attacks
Programming in the Large, 20044 Chair of SoftwareEngineering
Typing approaches
Pascal
x := yOnly if types of x and y are identical!
Smalltalk x.f always permitted, not static type check! At execution time: “Message not understood”
Programming in the Large, 20045 Chair of SoftwareEngineering
Like Pascal in basic forms
But polymorphism allows more flexible assignment rule:
x := y permitted if type of y “conforms to”type of x
Typed O-O languages
Programming in the Large, 20046 Chair of SoftwareEngineering
Basic type rules in typed O-O languages
Eiffel, Java, .NET...
In every assignment x := y (or argument passing), type ofy conforms to type of x.
In every feature call x.f(…)(qualified), f is an exportedfeature of the class of x.
C++: “A little bit typed”(Casts)
Programming in the Large, 20047 Chair of SoftwareEngineering
Terminology
Typed vs untyped languages
More accurate:
Statically typed, vs Dynamically typed
Programming in the Large, 20048 Chair of SoftwareEngineering
Typing is always pessimistic
Invalid in Pascal:
var n: INTEGER
n := 0.0
if 0 > 1 thenbegin
n := 0.0end
Programming in the Large, 20049 Chair of SoftwareEngineering
The basic goal
A programming language is statically typed if itsdefinition includes a set of type rules, guaranteeing thatno execution of a valid program will ever produce a run-time type failure.
A type rule is a validity constraint involving the typesassociated with program elements.
A validity constraint for a programming language is aboolean condition applicable to any syntactically legalprogram text in the language.
Programming in the Large, 200410 Chair of SoftwareEngineering
Precise definitions
An object-oriented program is class-level-valid if itsatisfies the following properties:
In every assignment x := y(or argument passing),type of y conforms to type of x.
In every feature call x.f(…)(qualified), f is anexported feature of the class of x.
Without catcalls, any class-level-valid program would betype-safe!
Programming in the Large, 200411 Chair of SoftwareEngineering
The issue: flexibility vs safety
Find a type system that:
Supports covariance and genericity Permits full static type checking
Stated differently: Disprove the “Pierre America conjecture” that one can
have at most two of polymorphic substitution,covariance, and static type checking
Fix the “holes” in Eiffel’s type system
Programming in the Large, 200412 Chair of SoftwareEngineering
A typical covariance situation
AR RAY ED _
BOAT
S TAC KCAT
Inherits
Client
captain
sail (...)
sail (...)
repair_second_hull
A RRA YED _
SKIPPER
STA CK
CAT_SKIPPER
captain
Programming in the Large, 200413 Chair of SoftwareEngineering
Original class
class BOAT feature
captain: SKIPPER-- Skipper assigned to this boat
sail (c: SKIPPER) is-- Appoint c as captain of this boat.
requirec /= Void
do captain := c
ensurecaptain = c
endend
AR RAY ED _
BOAT
S TAC KCAT
captain
sail (...)
sail (...)
A RRA YED _
SKIPPER
STA CK
CAT_SKIPPER
captain
Programming in the Large, 200414 Chair of SoftwareEngineering
Original class (simplified)
class BOAT feature
captain: SKIPPER
sail (c: SKIPPER) isdo
captain := cend
end
ARRAYED_
BOAT
STACKCAT
captain
sail (...)
sail (...)ARRAYED_
SKIPPER
STACKCAT_
SKIPPERcaptain
Programming in the Large, 200415 Chair of SoftwareEngineering
Heir class
class CAT inheritBOAT
redefinecaptain, sail
end
feature
captain: CAT_SKIPPER
sail (c: CAT_SKIPPER) isdo
captain := cend
end
AR RAY ED _
BOAT
S TAC KCAT
captain
sail (...)
sail (...)
A RRA YED _
SKIPPER
STA CK
CAT_SKIPPER
captain
Programming in the Large, 200416 Chair of SoftwareEngineering
Original class, using anchored type
class BOAT feature
captain: SKIPPER
sail (c: like captain) isdo
captain := cend
end
No explicit redefinition necessary for sailin CAT (see next)
AR RAY ED _
BOAT
S TAC KCAT
captain
sail (...)
sail (...)
A RRA YED _
SKIPPER
STA CK
CAT_SKIPPER
captain
Programming in the Large, 200417 Chair of SoftwareEngineering
Heir class
classCAT
inherit
BOATredefine
captainend
feature
captain: CAT_SKIPPER
end
Programming in the Large, 200418 Chair of SoftwareEngineering
Static typing vs. dynamic binding
x.f
Static typing: ensures that there is AT LEAST ONEFEATURE
Dynamic binding: ensures that it is THE RIGHT FEATURE
Programming in the Large, 200419 Chair of SoftwareEngineering
Catcalls
boat1: BOAT; cat1: CATskipper1: SKIPPER; cat_skipper1: CAT_SKIPPER...boat1 := cat1...boat1.sail (skipper1)
The captain of this catamaran is now a plain SKIPPER!
Might try to do captain.repair_second_hull (see next)
captain
(SKIPPER)(CAT)
“Ticking bomb”
Programming in the Large, 200420 Chair of SoftwareEngineering
Catcallsclass
BOATfeature
do_maintenance isdo -- Something here.end
end
feature do_maintenance is do
captain.repair_second_hull endend
class CAT inherit BOAT redefine do_maintenance end
Programming in the Large, 200421 Chair of SoftwareEngineering
Catcall situation
ARRAYED_
BOAT
STACKCAT
captain
sail (...)
sail (...)repair_second_hull
ARRAYED_
SKIPPER
STACKCAT_
SKIPPERcaptain
Programming in the Large, 200422 Chair of SoftwareEngineering
Consequences of a catcall
Crash?
Security attack?
Programming in the Large, 200423 Chair of SoftwareEngineering
Catcalls: source #2 — Genericity
skipper_list: LIST [SKIPPER]cat_skipper_list: LIST [CAT_SKIPPER]...skipper_list := cat_skipper_list
skipper_list.extend (skipper1)
cat_skipper1 := cat_skipper_list.last
Programming in the Large, 200424 Chair of SoftwareEngineering
Catcalls: source #3 — Descendant hiding
class RECTANGLE inheritPOLYGON
export{NONE}
add_vertex end...
end
poly1 := rect1...poly1.add_vertex (...)
Programming in the Large, 200425 Chair of SoftwareEngineering
CAT
Changed Availability or Type
Programming in the Large, 200426 Chair of SoftwareEngineering
Pierre America, 1990
At most two of:
Polymorphic substitution
Covariance
Static type checking
Programming in the Large, 200427 Chair of SoftwareEngineering
Previous solutions: novariance
C++, Java, .NET...
Eliminates the problem (obviously)
Forces programmers to do the conversions themselves
May result in brittle code
Programming in the Large, 200428 Chair of SoftwareEngineering
Previous solutions: contravariance
Results specialized, argumentsgeneralized
Solves the problem
Only problem: doesn’t matchpractical needs
The world seems to be covariant.
AR RAY ED _
BOAT
S TAC KCAT
captain
sail (...)
sail (...)
A RRA YED _
SKIPPER
STA CK
CAT_SKIPPER
captain
Programming in the Large, 200429 Chair of SoftwareEngineering
Previous solutions: catch catcalls
Generate code to check argumentsCause exception if wrong typeAvoids the security issue
Disadvantages: Performance penalty in all cases Forces issue on client! No easy way to force client to handle exception Exception too drastic
Programming in the Large, 200430 Chair of SoftwareEngineering
Previous solutions: Overloading
Consider that redefinition creates a new variant of the routine butdoesn’t obliterate the previous one.
Name resolution combines dynamic binding and overloading. Semanticrules can be devised (Giuseppe Castagna, ENS Paris)
Doesn’t seem compatible with goals of O-O programming
AR RAY ED _
BOAT
S TAC KCAT
captain
sail (...)
sail (...)
A RRA YED _
SKIPPER
STA CK
CAT_SKIPPER
captain
Programming in the Large, 200431 Chair of SoftwareEngineering
Previous solutions: system-level validity
Considering all assignments, compute dynamic type set(DTS) of any variable x.If there is an assignment x := y, or a correspondingargument passing, all elements of DTS of y are also in theDTS of x.
No attempt at control flow analysis Fixpoint algorithm Helps with optimization
Disadvantages: Pessimistic Not incremental Difficulty of giving precise diagnostics
Programming in the Large, 200432 Chair of SoftwareEngineering
Previous solutions: class-level validity
If there is an assignment x := y and y is of a differenttype from x, or (recursively) y is polymorphic, consider xpolymorphic.Any formal routine argument is polymorphicDisallow x. r (...) if x is polymorphic and r is a CATroutine.Local information, all incrementalDisadvantages:
Pessimistic Difficulty of giving precise diagnostics
Programming in the Large, 200433 Chair of SoftwareEngineering
Recent Eiffel developments
Tuples
Expanded inheritance
Programming in the Large, 200434 Chair of SoftwareEngineering
Tuple types and tuples
TUPLE [X, Y, Z]Denotes sequences of at least three elements, first of
type X, second of type Y, third of type Z
Individual tuple: [x1, y1, z1]
Conformance relations
TUPLE [X, Y, Z] TUPLE [X, Y]
Programming in the Large, 200435 Chair of SoftwareEngineering
Expanded inheritance
class C inheritA
expanded B
feature...
end
No polymorphism permitted:a1 := c1 -- OK
b1 := c1 -- Not permitted
C
B
Programming in the Large, 200436 Chair of SoftwareEngineering
The new solution (1)
Covariance etc. OK with expanded inheritance
Covariance also OK with non-exported features
x.f(a) -- Qualified
f(a) -- Unqualified
Programming in the Large, 200437 Chair of SoftwareEngineering
The new solution (2)
Allow covariant redefinition even with polymorphism!
Replacement (“recast”) must be provided
Also applies to generic case
Programming in the Large, 200438 Chair of SoftwareEngineering
Covariant cats
class CAT inheritBOAT
redefinecaptain, sail
end
feature
captain: CAT_SKIPPER
sail (c: CAT_SKIPPER) isrecast
trained_as_cat_skipperdo
captain := cend
end
AR RAY ED _
BOAT
S TAC KCAT
captain
sail (...)
sail (...)
A RRA YED _
SKIPPER
STA CK
CAT_SKIPPER
captain
Programming in the Large, 200439 Chair of SoftwareEngineering
A recast function
trained_as_cat_skipper (s: SKIPPER): CAT_SKIPPER is-- Version of skipper s reborn as cat skipper
requireexists: s /= Void
docreate Result.train_skipper (s)
end
Programming in the Large, 200440 Chair of SoftwareEngineering
In CAT_SKIPPER
class CAT_SKIPPER inheritSKIPPER
createmake_from_skipper
feature -- Initializationtrain_skipper (s: SKIPPER) is
requires /= Voids.trained_as_cat_skipper
do…
endend
Programming in the Large, 200441 Chair of SoftwareEngineering
The latest…
No more recast function
Use exceptions instead
sail (c: CAT_SKIPPER) isdo
captain := crescue
… Can use c …end
Programming in the Large, 200442 Chair of SoftwareEngineering
The multi-argument case
r (x: TYPE1 ; y: TYPE2; z: TYPE3) isrecast
transformdo
...end
withtransform (x: OLD1 ; y: OLD2; z: OLD3):
TUPLE [TYPE1, TYPE2, TYPE3] isdo
...end
Programming in the Large, 200443 Chair of SoftwareEngineering
The generic case
In C [G], if there is a routine
r (x: G)
it must have a recast clause!
Programming in the Large, 200444 Chair of SoftwareEngineering
Possible criticism
Creates a copy
What if LIST of catamarans
Programming in the Large, 200445 Chair of SoftwareEngineering
The descendant hiding case
Expanded inheritance works, of course
More flexibility: still under discussion
Programming in the Large, 200446 Chair of SoftwareEngineering
More work
ImplementAnalyze benefits and disadvantages furtherStudy real softwareFormalize through a mathematical model, proveSolve descendant hiding issue
Programming in the Large, 200447 Chair of SoftwareEngineering
Some tentative conclusions
Flexibility can be reconciled with safety
No need to choose betweenanarchy and “bondage and discipline”
Static typing is practical
Language design is neededLanguage design is funCommittees work!Don’t sail a catamaran unless you know how to