Introduction Local State Dispatching Real Life Types and Objects Objects Dr. Mattox Beckman University of Illinois at Urbana-Champaign Department of Computer Science
Introduction Local State Dispatching Real Life Types and Objects Objectives You should be able to... In this lecture we extend the idea of local state from last time to create a simple implementation of objects, and discuss its limitations. We will also show the message dispatch model of objects, which allows for inheritance and virtual functions. Your objectives: ◮ Be able to explain what an object is. ◮ Know how to implement an object using records and HOFs. ◮ Know how to implement an object using a message dispatcher. ◮ Explain the terms covariant and contravariant .
Introduction Local State Dispatching Real Life Types and Objects Preliminaries ◮ We will use the following functions during our discussion.... l e t p i 1 ( x , y ) = x l e t pi2 ( x , y ) = y l e t r e p o r t ( x , y ) = p r i n t _ s t r i n g ” P o i n t : ”; p r i n t _ i n t x ; p r i n t _ s t r i n g ” , ” ; p r i n t _ i n t y ; p r i n t _ n e w l i n e ( ) l e t movept ( x , y ) ( dx , dy ) = ( x+dx , y+dy )
let (lref,getx,gety,show,move) = mktPoint (2,4);; Introduction Local State Dispatching Real Life Types and Objects Point Here is an example of a point using local state. l e t mktPoint myloc = l e t myloc = r e f myloc i n ( myloc , ( fun ( ) − > p i 1 ! myloc ) , ( fun ( ) − > pi2 ! myloc ) , ( fun ( ) − > r e p o r t ! myloc ) , ( fun d l − > myloc := movept ! myloc d l ) ) ◮ This defjnes a tuple of functions that share a common state. ◮ It is cumbersome to use.
Introduction Local State Dispatching Real Life Types and Objects Improvement: Use records. type p o i n t = { l o c : ( i n t * i n t ) r e f ; getx : u n i t − > i n t ; gety : u n i t − > i n t ; draw : u n i t − > u n i t ; move : i n t * i n t − > u n i t ; } l e t mkrPoint newloc = l e t myloc = r e f newloc i n { l o c = myloc ; getx = ( fun ( ) − > p i 1 ! myloc ) ; gety = ( fun ( ) − > pi2 ! myloc ) ; draw = ( fun ( ) − > r e p o r t ! myloc ) ; move = ( fun d l − > myloc := movept ! myloc d l ) }
Introduction Local State Dispatching Real Life Types and Objects Adding Self By the way, this lecture is really about recursion. l e t mkPoint newloc = l e t r e c t h i s = { l o c = r e f newloc ; getx = ( fun ( ) − > p i 1 ! ( t h i s . l o c ) ) ; gety = ( fun ( ) − > pi2 ! ( t h i s . l o c ) ) ; draw = ( fun ( ) − > r e p o r t ! ( t h i s . l o c ) ) ; move = ( fun d l − > t h i s . l o c := movept ! ( t h i s . l o c ) d l ) } i n t h i s ; ; We can store “this” explicitly in the record if we want.
Introduction Local State Dispatching Real Life Types and Objects Message Dispatching Last time we said that an object is a kind of data that can receive messages from the program or other objects. ◮ Q: How do we normally represent messages? ◮ A: With strings! Let a point object be a function which takes a string and returns an appropriate function matching that string. ◮ Question: Suppose p is our point object. What will be its type?
Introduction Local State Dispatching Real Life Types and Objects mkPoint l e t mkPoint x y = l e t x = r e f x i n l e t y = r e f y i n fun s t − > match s t with | ” getx ” − > ( fun _ − > ! x ) | ” gety ” − > ( fun _ − > ! y ) | ”movx” − > ( fun nx − > x := ! x + nx ; nx ) | ”movy” − > ( fun ny − > y := ! y + ny ; ny ) | _ − > r a i s e ( F a i l u r e ”Unknown message . ” ) All methods now have to have type int -> int .
Introduction Local State Dispatching Real Life Types and Objects Subclassing ◮ Warmup exercise: How would we add a report method? ◮ Another one: How would we add this support? Let’s say we want a fastpoint , which moves twice as fast as the original point. What does it mean for fastpoint to be a subclass of point ? ◮ fastpoint should respond to the same messages. ◮ It may override some of them. ◮ It may add its own. ◮ It may not remove any methods. ◮ The fastpoint object will need access to some of the data in point .
Introduction Local State Dispatching Real Life Types and Objects Implementing ◮ Two entities involved: the superclass ( point ) and the subclass ( fastpoint ). ◮ fastpoint needs to create an instance of point . ◮ point construction needs to return the “public” data to fastpoint . ◮ fastpoint returns a dispatcher: ◮ if the fastpoint dispatcher can handle a message, it does. ◮ Otherwise, it sends the message to point .
Introduction Local State Dispatching Real Life Types and Objects Code: point l e t mkSuperPoint x y = l e t x = r e f x i n l e t y = r e f y i n ( ( x , y ) , (* T h i s p a r t r e t u r n s the l o c a l s t a t e *) fun s t − > match s t with | ” getx ” − > ( fun _ − > ! x ) | ” gety ” − > ( fun _ − > ! y ) | ”movx” − > ( fun nx − > x := ! x + nx ; nx ) | ”movy” − > ( fun ny − > y := ! y + ny ; ny ) | _ − > r a i s e ( F a i l u r e ”Unknown message . ” ) ) ; ; v a l mkSuperPoint : i n t − > i n t − > ( i n t r e f * i n t r e f ) * ( s t r i n g − > i n t − > i n t ) = <fun >
Introduction Local State Dispatching Real Life Types and Objects Code: fastpoint l e t mkFastpoint x y = l e t ( ( x , y ) , super ) = mkSuperPoint x y i n fun s t − > match s t with | ”movx” − > ( fun nx − > x := ! x + 2 * nx ; nx ) | ”movy” − > ( fun ny − > y := ! y + 2 * ny ; ny ) | _ − > super s t ; ; ◮ This technique is fmexible; we can add methods very easily. ◮ But it’s also slow. Imagine if we had a chain of 20 classes....
x y movy movx vtable Introduction Local State Dispatching Real Life Types and Objects C++ ◮ Methods and variables are kept in a table: a fjxed location. ◮ “ this ” is an implicit argument, allowing only one copy of the function to be needed. ◮ Virtual methods are kept in a vtable , which counts as local data. value of x Local data for point or fastpoint : value of y pointer to vtable pointer to point.movx Vtable for point : pointer to point.movy ( fastpoint vtable is similar.) getx , etc. is static.
Introduction Local State Dispatching Real Life Types and Objects Discussion ◮ Other languages (i.e., smalltalk) use a technique very similar to this one. ◮ Java uses the “every object is of type Object ” technique. ◮ A strong type system makes it somewhat cumbersome to simulate objects. You either have to: ◮ defjne a new type to encompass all objects, or ◮ force all methods to have the same type. ◮ Important concept: polymorphism — when functions can operate on multiple types. (This is different than overloading — when multiple functions exist with the same name, but different inputs.)
Introduction Local State Dispatching Real Life Types and Objects How do types relate? ◮ How can you tell if one type is a subtype of another? ◮ Are integers subtypes of fmoats? (Or vice-versa?) ◮ Characters / strings? ◮ Squares / Shapes? ◮ An integer is a kind of fmoat, so we can say that integer is a subtype of fmoat.
Introduction Local State Dispatching Real Life Types and Objects How do types relate? ◮ How can you tell if one type is a subtype of another? ◮ Are integers subtypes of fmoats? (Or vice-versa?) ◮ Characters / strings? ◮ Squares / Shapes? ◮ An integer is a kind of fmoat, so we can say that integer is a subtype of fmoat. Float Int
Introduction Local State Dispatching Real Life Types and Objects Covariance ◮ Some types take parameters, such as lists and trees. ◮ If the subtype relationship varies according to the input type, the type is said to be covariant . ◮ “Most” types containing parameters are covariant. [Float] Float [Int] Int
Introduction Local State Dispatching Real Life Types and Objects Functions ◮ Functions are an important exception! ◮ The function type is covariant with respect to the output. If we are expecting a function that outputs a fmoat, I can give you a function that outputs an integer without breaking anything. The reverse is not true! ◮ The function type is contravariant with respect to the input. If we are expecting a function that takes a fmoat, providing a function that takes an integer will fail or truncate the input. Int → Float Int → Int Float → Float Float → Int
Introduction Local State Dispatching Real Life Types and Objects The trouble with objects.... Actually, there’s more than just this one... p u b l i c c l a s s A { p u b l i c A foo (A x ) { . . . } p u b l i c A bar ( ) { /* c a l l s foo . . . */ } } p u b l i c c l a s s B : A { p u b l i c B foo (B x ) { . . . } } ◮ B.bar inherits from A ◮ But B.foo overwrites A.foo . ◮ When A.bar calls B.foo , what will happen?
Recommend
More recommend