cs 251 fall 2019 cs 251 fall 2019 oo essence principles
play

CS 251 Fall 2019 CS 251 Fall 2019 OO essence: Principles of - PowerPoint PPT Presentation

CS 251 Fall 2019 CS 251 Fall 2019 OO essence: Principles of Programming Languages Principles of Programming Languages Ben Wood Ben Wood Program design principles? Subtyping Objects model state/behavior of real-world


  1. λ λ CS 251 Fall 2019 CS 251 Fall 2019 OO essence: Principles of Programming Languages Principles of Programming Languages Ben Wood Ben Wood • Program design principles? Subtyping – Objects model state/behavior of real-world entities/concepts? Kinda – Organization by classification and encapsulation and Substitutivity – Reuse via implicit extensibility • Key semantics: – Late binding / dynamic dispatch – Su Substitutability and subtyping – Inheritance or delegation Will contrast function-oriented principles/semantics later. https://cs.wellesley.edu/~cs251/f19/ 1 Subtyping 2 Subtyping Subtyping and substitutability Subtyping and substitutability class Rectangle { void f() { void f() { private int x,y,w,h; Rectangle r = Rectangle r = void moveTo(int x, int y); new Rectangle (); new FilledRectangle (); void setSize(int width, int height); r.moveTo(100,100); r.moveTo(100,100); void show(); void hide(); r.hide(); r.hide(); } } } Which are Wh e safe? e? class FilledRectangle { private int x,y,w,h; void g() { void g() { private Color c; void moveTo(int x, int y); FilledRectangle r = FilledRectangle r = void setSize(int width, int height); new FilledRectangle (); new Rectangle (); void show(); r.moveTo(100,100); r.moveTo(100,100); void hide(); r.setFillColor(Color.red); r.setFillColor(Color.red); void setFillColor(Color color); r.hide(); r.hide(); Color getFillColor(); } } } Subtyping 3 Subtyping 4

  2. Subtyping: broad definitions Type variable instantiation is NO NOT subtyping. Parametric polymorphism ≠ subtype polymorphism Job of type system: Jo If a program type-checks, th then evaluation of the program never If applies an operation to an incompatible value. map : ('a -> 'b) -> 'a list -> 'b list Ne New type relation: T <: U "Type T is a subtype of type U." f : int -> int Sound on only if all operations that are valid on values of type U are also valid on values of type T. xs : int list New type-ch Ne checki cking rule le: If e : T and T <: U th If then e : U . ß type-check (map f xs) : int list Principle: substitutability. type variable instantiation: 'a = int, 'b = int ML ML has no su subtyping Subtyping 5 Subtyping 6 Mutable Records (made-up lang.) A made-up language for subtyping data (half like ML, half like Java) ation (field names and contents): Record cr creat {f1=e1, f2=e2, …, fn=en} • Can cover most core subtyping ideas by Evaluate all ei , make a record considering re records wi with mutable fields Record field acce access : e.f Evaluate e to record v with an f field, get contents of f field • Make up our own syntax e1.f = e2 Record field up update – ML records, no subtyping or field-mutation Evaluate e1 to a record v1 and e2 to a value v2 ; – Racket and Smalltalk: no static type system Change v1 's f field (which must exist) to v2 ; Return v2 – Java is verbose Subtyping 7 Subtyping 8

  3. A Basic Type System Type system is so sound (safe). Record ty Re types : fields a record has, type for each field Does this program type check? Can it ever try to access a non-existent field? {f1:t1, f2:t2, …, fn:tn} Ty Type-ch check ecking expressions: fun distToOrigin (p:{x:real,y:real}) = • If e1 : t1 , … , en : tn Math.sqrt(p.x*p.x + p.y*p.y) then {f1=e1,…,fn=en} : {f1:t1,…,fn:tn} val p : {x:real,y:real} = • If e : {…,f:t,…} {x=3.0, y=4.0} then e.f : t • If e1 : {…,f:t,…} and e2 : t , val five : real = distToOrigin( p ) then e1.f = e2 : t Subtyping 9 Subtyping 10 Type system is so sound (safe) . Why not allow extra fields? Natural idea of related types: if expression has type Na Does this program type check? Can it ever try to access a non-existent field? {f1 : t1, f2 : t2, ..., fn : tn} Then it also can have a type with a subset of those fields. fun distToOrigin (p:{x:real,y:real}) = Math.sqrt(p.x*p.x + p.y*p.y) fun distToOrigin (p:{x:real,y:real}) = … val c : {x:real,y:real,color:string} = fun makePurple (p:{color:string}) = {x=3.0, y=4.0, color="green"} p.color = "purple" val c :{x:real,y:real,color:string} = val five : real = distToOrigin( c ) {x=3.0, y=4.0, color="green"} val _ = distToOrigin(c) But type system is (too?) conservative. val _ = makePurple(c) Subtyping 11 Subtyping 12

  4. Changing the type system 4 reasonable subtyping rules Princ Pr nciple: su substitutability So Soluti ution: n: 2 additions, no changes If t1 <: t2 , then values of type t1 must be usable in every way values of type t2 are. – su subtypi ping rel relation : t1 <: t2 " t1 is a subtype of t2 " 1. 1. “Wi Width” subtyping: A supertype can have a subset of fields with the same types. – ne new ty typing ng ru rule: 2. 2. “P “Permutation” ” su subtyping: If e : t1 and t1 <: t2 , A supertype can have the same set of fields with the same types in a different order. then (also) e : t2 3. 3. Transitivity: Tr If t1 <: t2 and t2 <: t3 , then t1 <: t3 . 4. 4. Reflex Re exivity: No Now def efine e t1 <: t2 Every type is a subtype of itself: t <: t May seem unnecessary, but simplifies other rules in large languages Subtyping 13 Subtyping 14 Depth subtyping? Depth subtyping? fun circleY (c:{center:{x:real,y:real}, r:real}) = fun circleY (c:{center:{x:real,y:real}, r:real}) = c.center.y c.center.y val sphere:{center:{x:real,y:real,z:real}, r:real} = val sphere:{center:{x:real,y:real,z:real}, r:real} = {center={x=3.0,y=4.0,z=0.0}, r=1.0} {center={x=3.0,y=4.0,z=0.0}, r=1.0} val _ = circleY(sphere) val _ = circleY(sphere) Does this currently type-check? Does it ever try to use non-existent fields? Ty Type checks only if: How could we change the type system to allow it? {center:{x:real,y:real,z:real}, r:real} <: Should we? {center:{x:real,y:real}, r:real} Subtyping 15 Subtyping 16

  5. Adding depth subtyping St Stop! Ne New subt btyping ru rule: We added a new subtyping rule If ta <: tb , to make type system more flexible. then {f1:t1, …, f: ta , …, fn:tn} <: {f1:t1, …, f: tb , …, fn:tn} But is it sound? Bu Does it allow any program that accesses non- fun circleY (c:{center:{x:real,y:real}, r:real}) = c.center.y existent fields? val sphere:{center:{x:real,y:real,z:real}, r:real} = {center={x=3.0,y=4.0,z=0.0}, r=1.0} val _ = circleY(sphere) Does it type-check now? Subtyping 17 Subtyping 18 Mutation strikes again Moral of the story In a language with records/objects with mu mutable fields , dept de pth subtypi ping is uns unsound und. Subtyping ca Su canno nnot t allow ch changi nging ng th the typ type of mu mutable fields. fun setToOrigin (c:{center:{x:real,y:real}, r:real})= c.center = {x=0.0, y=0.0} If fields are im immutable , then de dept pth subtypi ping is sound ! val sphere:{center:{x:real,y:real,z:real}, r:real} = {center={x=3.0, y=4.0, z=0.0}, r=1.0} Choose at most two of three: val _ = setToOrigin(sphere) – mutability val _ = sphere.center.z (* kaboom! (no z field) *) – depth subtyping – soundness Subtyping 19 Subtyping 20

  6. !!! !!! !!! !!! Subtyping mistakes: Java (really) What??? if t1 <: t2 , then t1[] <: t2[] Wh Why allow it? "Covariant array subtyping" Object[] System.arrayCopy(Object[] src) {…} Seemed especially important before generics class Point { … } What goes wrong? Wh class ColorPoint extends Point { … } … void replaceFirst(Point[] pts) { pts[0] = new Point(3,4); } String m2(int x) { ColorPoint[] cpts = new ColorPoint[x]; for(int i=0; i < x; i++) "F "Fix:" :" dynamic checking on every non-primitive array store. cpts[i] = new ColorPoint(0,0,"green"); replaceFirst(cpts); ArrayStoreException return cpts[0].color; } Subtyping 21 Subtyping 22 !!! !!! !!! !!! From Bill Joy (Sun Cofounder) Hypothetical: Allow subclass C to change type of field from Date: Fri, 09 Oct 1998 09:41:05 -0600 From: bill joy superclass in scope of C Subject: …[discussion about java genericity] – To unrelated type actually, java array covariance was done for less noble reasons …: it – To supertype of field's original type made some generic "bcopy" (memory copy) and like operations much – To subtype of field's original type easier to write... I proposed to take this out in 95, but it was too late (...). i think it is unfortunate that it wasn't taken out... Which ones go wrong? it would have made adding genericity later much cleaner, and [array covariance] doesn't pay for its complexity today. wnj Subtyping 23 Subtyping 24

Recommend


More recommend