Title: CS
11321
2CS1321Introduction to Programming
- Georgia Institute of Technology
- College of Computing
- Lecture 25
- April 9, 2002
3Todays Menu
- Introducing Object Oriented Programming
- Modeling
- Abstract Data Types (Queue)
- Scheme implementation tricks
- Coke Machines
4Object-Oriented Programming
5Background
- We now know the prerequisite capabilities
- Persistent structures (vectors)
- Encapsulating Definitions (local)
- We will combine these components as a brief
introduction to the third programming paradigm
Object-Oriented Programming
6Introduction
- We will not abandon the principles you have
learned so far - modularity
- abstraction
- the necessity of testing the logical components
before integrating and testing the whole thing
7Object Oriented Programming
- A different programming style
- A different way of thinking
- Origins
- Problems with very large systems becoming
unmanageable (gt 100,000 lines of code) - Graphical User Interfaces (e.g. Macintosh,
Windows) required a different way of programming
due to complex interactions of windows, mouse
clicks, etc. - Xerox PARC Smalltalk
- C as an enhancement to C
- Java
8Lets Imagine
- You graduated cum laude from Georgia Tech.
- Bad news When you attack the job market, there
is nothing for you in the field you hoped for. - Good news the only visionary person in local
politics has just been put in charge of your
local Department of Transportation - They need some serious analysis capability to
prepare for some road improvements
9Specifically,
- This person wants funding to improve the local
traffic flow. - This means justifying the cost of this by showing
how the proposed construction will improve the
traffic flow - They need a program to model the behavior of the
local road traffic - As it is now
- As it would be after the construction is finished
- As it will be during construction
Mark of a truly visionary traffic engineer
10Your Plan
- Sit down with this potential employer and sketch
out what the result should look like. - Make sure you know where all the information is
coming from. - Figure out how to implement the system.
- Amazing as you start this conversation, the
person jumps up, shakes your hand, and asks when
you can start.
11So now you actually have to
12Heres what you need
13Components of the Model
- Vehicles
- Where are they coming from?
- Where are they going?
- Behavior?
- Road Segments
- Capacity?
- Speed limit?
- Intersections
- Flow control?
14A Road Segment
Vehicles decide which way to turn
Intersection controls which queues empty
What kind of collection?
(FIFO) queue
A collection of vehicles moving at the speed
limit
A collection of vehicles not moving
15Model Components
- Street segments
- Connect intersections
- Contain two queues (moving, waiting)
- Queues contain vehicles
- Vehicles have state and methods
- Location, fuel, passengers, route
- Move, turn, pick up, drop off
- System behavior results from the interactions
between intersections and vehicles
16Designing Components
- Collections (queues, stacks)
- Objects (coke machines, vehicles)
17The Scenario
- Recall the concept of a Queue
- Defined by a set of behaviors
- Enqueue
- Dequeue
- IsEmpty?
18Where is the Queue model?
- The logical idea of the queue consists of
- Data stored in some structure
- Modules to act on that data
- But where is the actual queue?
- Wed like some way of representing sucha concept
in our programs.
19Why?
- We would like to have reusable drop-in
programming components we could use to solve
problems or simulate behavior. - We would like to encapsulate the data and the
behaviors in order to protect it from misuse. - We would like clear interfaces between different
parts of programs - We would like a programming system that was
extensible - We would like a programming language that would
be excellent for modeling real world objects
20Issues
- If our queue could somehow be packaged we could
drop in a queue object whenever we needed to
represent queue behavior.
Queue
Acme Manufacturing
21Issues
Contract The party of the first part hereinafter
known as the queue agrees to... The party of the
second part hereinafter known as the application
agrees to...
Clear lines of responsibility
22Objects
Elevator
Signal Object
Elevator Object
Student Object
Car Object
BankAccount Object
Real World Objects!
23Abstraction in Object-Oriented Programming
24Procedural Abstraction
- Procedural Abstractions organize instructions.
Function Power Give me two numbers (base
exponent) Ill return to you baseexponent ???
Implementation ???
25Data Abstraction
- Data Abstractions organize data.
StudentType
Name (string) GPA (num) Letter Grade
(char) Student Number (num)
26Behavioral Abstraction
- Behavioral Abstractions combine procedural and
data abstractions.
27The Object-Oriented Paradigm
- Instances of behavioral abstractions are known as
objects. - Objects have a clear interface by which they send
and receive messages (communicate). - OO is a design and approach issue. Just because
a language offers object-oriented features
doesnt mean youre doing OO programming.
28Information Hiding
- Information Hiding means that the user has enough
information to use the interface, and no more
Example Stick shift We dont care about the
inner workings... We just want to get the car
going!
29Revisiting the Question Where is the Queue?
- Notice we still have no way of identifying the
idea were discussing - The Queue is still in the ether.
- Wed like to encapsulate the data (regardless of
its actual representation) with the behavior
(methods). - Once we do this, weve got a logical entity to
which we can point and say, there it is!
30Abstract Data Types
- An idea, a concept, an abstraction of the big
picture - It encapsulates the abstract behaviors and data
implied by the thing being modeled.
Queue
peek
enqueue
Data State
dequeue
IsEmpty?
Initialize
31Achieving Behavioral Abstraction
- Abstract data types (ADTs) are concepts.
- We require some way to implement these common
abstractions so we can write them once, verify
that they are correct, and reuse them. - This would save us from having to re-do work.
For example, every time we create a queue we did - (define its-list empty)(define (enqueue item
list) )(define (dequeue list) ) - (define (IsEmpty? list ) )
- We need a construct that will allow us to bundle
these things together.
32The Story So Far
- Behavioral abstraction combines data abstraction
with procedural abstraction. - The object-oriented paradigm focuses on the
interaction and manipulation of objects. - An Abstract Data Type (ADT) allows us to think of
what were representing as a thing regardless of
its actual implementation.
33Questions?
34Classes and Instances
- When we used (define-struct ltnamegt ) , it
merely indicated the character of the structure - We need to use (make-ltnamegt ) to create an
instance of this structure. - Similarly, we will define a special kind of
function with a rather odd syntax to define a
class - This will be a function that returns a function
definition!. - We will then need to define instances of that
class to model actual objects. - We animate these objects by evaluating the
instances
35Components of a Class Definition
- Stored attributes local data indicating the
current state of any instance. - Private methods functions hidden from the user
to implement behavior. - Public methods functions invoked by the user to
manipulate the object. - Constructor method to initialize the local
state of this object. - Manager direct access to each of the public
methods. - Unique to the Scheme implementation of classes
and objects
36Scheme Guts
- How (local ) really works
37Keeping State in Functions
Up until this point, this has been the norm for
the manner in which our functions work
38Keeping State in Functions
Up until this point, this has been the norm for
the manner in which our functions work
Based on this behavior, we have some sort of
function called add-one-to-number that takes in
a number and simply adds one to it.
39So long as we keep passing the same argument as a
parameter to our function, the results will
always be the same one plus the number passed
in. So what if there were another way to go about
doing this?
40What if we wanted
41What if we wanted
Here we appear to be changing some state value
permanently by adding our argument to it.
42Of course
We could create this situation with the above
code. Here we globally define a state variable
and rely on a function add-state-to-number to
set that value to a new value. It works, right?
Whats wrong with this approach?
43The problem
Well, our state variable is global. Which
means that every Tom, Dick, and Harry can access
and change our state variable without our
permission.
44A Solution?
Local seems to be well suited for our needs. It
creates a state variable that no one but the
actual function has access to, which is what we
wanted. But theres still a problem
45Back to the beginning
Well, it seems weve come back to our original
problem where we werent keeping state. Every
time we enter first-attempt, the local
expression which defines the state variable is
re-evaluated, setting us back to 0. So we can
never advance
46It would seem
It kind of looks like there really isnt a way to
create a local state variable within a function
and be able to permanently change its value every
time we perform that function.
Actually, there is. Take a gander at the
following
47(define (create-adder) (local (define state
0) (define (nxt delta)
(set! state ( state delta))) nxt))
This is a rather odd function. It seems to
return a function body rather than a value. Why
dont we try binding that function body to a name
and running it a few times
48This is definitely odd behavior. We evaluated
(create-adder), which gave us a function body.
When we called that function body, it seems weve
somehow created a state variable within our
function thats permanent. Lets look at the
code again
49(define (create-adder) (local (define state
0) (define (nxt delta)
(set! state ( state delta))) nxt))
We create a state variable within our local, as
we tried to do before
50(define (create-adder) (local (define state
0) (define (nxt delta)
(set! state ( state delta))) nxt))
But then we use that variable within another
local function that we define inside our
create-adder function.
51(define (create-adder) (local (define state
0) (define (nxt delta)
(set! state ( state delta))) nxt))
Create-adder returns the function body that it
had defined within the local. And thus lies
Schemes dilemma How do we return a function
body that uses value if value is defined locally
to create-adder?
52Schemes solution
Function Body
Scheme realizes that the function body returned
by create-adder needs to use the value stored in
state. So it sends off a function body with its
own copy of state internal to the function
body. It creates a truly local state variable.
Copy of state
53And so
We can bind that function body to a name (as
shown above). Whenever we call that function
body, it permanently changes the value of the
internal variable that it carries within the
function.
54Our Adventures Thus Far
So we can now keep local state within functions.
(define (create-adder) (local (define state
0) (define (nxt delta)
(set! state ( state delta))) nxt))
55Each time we call (create-adder), it returns to
us a lambda body that is linked to one specific
instance of the local data, namely the variable
called state. This lambda body utilizes a
variable called state that was defined inside
the local scope of the function create-adder but
outside the body of the lambda body returned.
(define (create-adder) (local (define state
0) (define (nxt delta)
(set! state ( state delta))) nxt))
56(No Transcript)
57Each of these calls to create-adder results in a
completely independent function body with its
own copy of the internal variable that it can act
upon.
58So what have we done?
- Weve managed to bind together two concepts until
this point we have had to consider as separate
items in Scheme - A sense of state (a collection of values and
variables that exist before a function is called,
that may be altered by a function during the
course of its execution and that continue to
exist after the function ceases) - Functionality that can act on a set values,
variables and parameters.
59The Secret of (local )
- (local ) actually does much more than just
encapsulate data and/or functions. - It postpones evaluation.
- The items inside (local ) are not defined until
the (local ) is executed. - This is both the reason (local ) works and what
makes OO programming in Scheme messy. - Do we care?
- About the guts? NO!
- About how to use them?
60Giving this idea a name
In Scheme, this concept is called a lexical
closure (or more simply, a closure). The idea of
closures begins to map very closely to a much
larger Computer Science concept Object
Oriented Programming. Lexical closure can be
tough to understand. We will take the
Engineering (information hiding) approach that we
dont have to understand it to be able to use it
just tell me how!
61Implementing Objects
- Collections, e.g. a Queue
- Enqueue, Dequeue, IsEmpty?
- Independent of what data goes into the queue
- Objects
- Coke Machine
- Vehicles (next time)
62Remember the Queue?
- Defined by a set of behaviors
- Enqueue
- Dequeue
- IsEmpty?
63Components of a Scheme Object
- make-queue -gt (-gt true )
- to create a queue
- (define (make-queue)
- (local ((define q empty) storage
- (define (init ) ) initialization
- (define (enqueue ) ) methods
- (define (dequeue ) ) methods
- service-manager symbol -gt ( -gt true)
- (define (service-manager msg)
- (cond
- (symbol? msg 'init) init
- (symbol? msg 'enqueue) enqueue
- else (error 'queue "illegal
operation")))) - (begin
- (init) the Constructor
- service-manager))) return a lambda
function
64Using Queues
Create three queue instances
- (define queue1 (make-queue))
- (define queue2 (make-queue))
- (define queue3 (make-queue))
- ((queue1 'enqueue) 1)
- ((queue1 'enqueue) 2)
- ((queue1 'enqueue) 3)
- ((queue1 'enqueue) 4)
- ((queue1 'enqueue) 5)
- ( ((queue1 'dequeue)) 1)
- ((queue2 'enqueue) 'a)
- ((queue2 'enqueue) 'b)
- ((queue2 'enqueue) 'c)
- (symbol? ((queue2 'dequeue)) 'a)
- ((queue3 'enqueue) ((queue1 'dequeue)))
- ((queue3 'enqueue) ((queue2 'dequeue)))
- ( ((queue3 'dequeue)) 2)
- (symbol? ((queue3 'dequeue)) 'b)
- ((queue3 'dequeue))
Load one queue with numbers
Note the extra () wrapping the service manager
call
Load second queue with symbols
Load third queue from the first and second
Third queue is empty
65queue.scm
66Questions?
67Whats an Object?
You are.
Seriously. You are an object. So is the chair
youre sitting on, the screen youre looking at,
the books you lug along with you every day, the
paper you write on, the pencils you write
with. Objects, in their purest sense, originated
as an attempt to model reality. In the real
world data and functionality do not exist as
separate entities floating in space. In the real
world, data is contained within objects, and can
only be access or modified via behaviors.
68Ah.the king of caffeinated beverages. Have you
ever thought about how much money is plunked into
vending machines every day to buy these things?
Its a hefty hunk of change. So why dont we
get in on the action? We wish to model a coke
machine in Scheme, using this idea of lexical
closures and object-oriented behavior.
69Coke Machine The State Variables
Real coke machines have varying capacities Real
coke machines hold money. Real coke machines
associate a cost with each coke.
(define cans 0) (define MAX-CANS 0) (define COST
.65) (define cash 0)
Even though max-cans is effectively going to be a
constant, were still going to start it off at
zero. This will allow us to create coke machines
with varying capacities.
70Coke Machine Initialization
We need to be able to specify the maximum number
of cans our coke machine can hold, and initialize
the number of cans we currently hold to that
value
(define (init-machine in-max) (begin (set!
MAX-CANS in-max) (set! cans MAX-CANS)))
71Coke Machine reload
If we run out of cokes in our coke machine, we
need to be able to reload our coke machine.
Lets simplify the problem by only reloading to
our maximum capacity
(define (reload) (set! cans MAX-CANS))
72Coke Machine is-empty?
Now we need a function that returns whether or
not a coke machine is empty.
(define (is-empty?) ( cans 0))
73New Coke Machine vend
Finally, something complex! Logically, we need to
be able to vend a single coke if the machine is
NOT empty. We also need to take in an idea of
cash. If the machine takes in AT LEAST the cost
of a can of coke, and if one is available, we
need to vend a coke, add money to the amount of
cash in the machine, and return the appropriate
change. If the user inserts the incorrect amount
of change, we need to handle that as well
74New Coke Machine vend
(define (vend in-money) (cond (is-empty?)
(display "No cokes left!")) else
(cond (gt in-money COST)
(begin (display "Have a
Coke") (set! cash ( cash
COST)) (set! cans (- cans
1)) (- in-money COST))
else (display
"Add more money"))))
75New Coke Machine how-many
For testing purposes, lets put this function in
(define (how-many) cans)
76Before we go on
Scheme is not exactly the most beautiful language
to emulate this Object Oriented behavior. The
next function were about to see is ugly and
confusing at first. So before we lose ourselves
in those particulars, lets examine what weve
set ourselves up for
77OBJECT
Our goal is to create an object that represents a
coke machine. This object will have values
contained within it and behaviors that act on
those values.
78New Coke Machine service-manager
(define (service-manager service) (cond
((symbol? service 'is-empty?) is-empty?)
((symbol? service 'how-many) how-many)
((symbol? service 'reload) reload)
((symbol? service 'vend) vend) (else
(display "Invalid service"))))
Note Although (vend ) requires a parameter,
you still just invoke its name.
79make-coke-machine
(define (make-coke-machine max) (local ((define
cans 0) (define MAX-CANS 0)
(define COST .65)
(define cash 0) (define
(init-machine in-max)
(define (reload) ) (define
(is-empty?) ) (define
(how-many) ) (define (vend
in-money) ) (define
(service-manager service) ) )
))
The definitions for these functions are on the
previous slides. Lets look at what the local
actually executes
80make-coke-machine
(define (make-coke-machine max) (local
() (begin (init-machine
max) service-manager)))
We begin by initializing our coke-machine
object. We then return the service manager
(the main functionality) as is typical in
closures.
81Lets figure out how this works
82The functionality that we returned from
make-coke-machine was this
(define (service-manager service) (cond
((symbol? service 'is-empty?) is-empty?)
((symbol? service 'how-many) how-many)
((symbol? service 'reload) reload)
((symbol? service 'vend) vend) (else
(display "Invalid service"))))
As we didnt provide any contracts for our
functions (shame on us!), were going to have to
play around with this function to see what
happens. It looks like this function takes in 4
different types of symbols. Lets try how-many
83(No Transcript)
84(No Transcript)
85(No Transcript)
86(No Transcript)
87(No Transcript)
88Patterns
- So it would seem that we use objects like this
- We create an instance of our object and bind it
to a name. This instance of our object is in
fact the service-manager for our closure. - (define ltobject-namegt (ltobject creatorgt))
- We act on that service manager by passing it the
name of the functionality we want to enact - (ltobject-namegt ltname of functionalitygt)
- This returns to us the actual functionality
itself, which we can then pass parameters to and
use - ((ltobject-namegt ltname of functionalitygt)
ltparametergt)
89Far-fetched?
Well, not terribly. In Java, the language youll
be working with next semester, you can definitely
draw parallels between what we just did and what
you will do CokeMachine CSCokeMachine new
CokeMachine(30) CSCokeMachine.vend(1.00) Syste
m.out.println( CSCokeMachine.howMany())
90Far-fetched?
Well, not terribly. In Java, the language youll
be working with next semester, you can definitely
draw parallels between what we just did and what
you will do CokeMachine CSCokeMachine new
CokeMachine(30) CSCokeMachine.vend(1.00) Syste
m.out.println( CSCokeMachine.howMany())
Here we bind a name to a coke machine object
91Far-fetched?
Well, not terribly. In Java, the language youll
be working with next semester, you can definitely
draw parallels between what we just did and what
you will do CokeMachine CSCokeMachine new
CokeMachine(30) CSCokeMachine.vend(1.00) Syste
m.out.println( CSCokeMachine.howMany())
Here we access functionality and pass a parameter
via ltobject namegt.ltfunctionalitygt(ltparametersgt)
92Far-fetched?
Well, not terribly. In Java, the language youll
be working with next semester, you can definitely
draw parallels between what we just did and what
you will do CokeMachine CSCokeMachine new
CokeMachine(30) CSCokeMachine.vend(1.00) Syste
m.out.println( CSCokeMachine.howMany())
And we do the same here ltobject
namegt.ltfunctionalitygt(ltparametersgt)
93Alternatives?
Is this the best way to model a coke machine?
Certainly not. Were missing a whole mess of
functionality. But lets talk about that next
time.
94Questions?
95(No Transcript)