Programmering: Abstraktion och modellering VT 2015 TDDC74

advertisement
TDDC74 Programmering:
Abstraktion och modellering
VT 2015
Johannes Schmidt
Institutionen för datavetenskap
Linköpings universitet
Lecture 9
Mutable structres, ADTs, OOP
•
•
•
•
Abstract data types: queue, stack
Mutable pairs, lists: singly / doubly linked list
Object Oriented Programming (OOP) in Racket
SICP-Book chapter: 3
An abstract data type: Stack
Think of a stack as a pile of books (items):
TOS: Top Of Stack.
Insertion (push) and extraction (pop) only at the TOS. LIFO = last in, first out
An abstract data type: Stack
ADT Stack
Methods:
•push: put a given item on the stack. This item is then the new TOS.
•pop: remove the TOS-item and return it.
Optional methods:
•size: determine the number of elements currently in the stack.
•empty?: check whether the stack is empty.
•peek: return the TOS-item without removing it.
An abstract data type: Queue
Think of a queue as a queue of people (items):
Insertion (enqueue) at the rear, extraction (dequeue) at the front. FIFO = first in, first out
An abstract data type: Queue
ADT Queue
Methods:
•enqueue: put a given item into the queue, at the rear.
•dequeue: remove an item from the queue, at the front.
Optional methods:
•size: determine the number of elements currently in the queue.
•empty?: check whether the queue is empty.
•peek: return the front-item without removing it.
How to implement
a stack, a queue?
Singly linked list
Doubly linked list?
Doubly linked list
A doubly linked list with insertion and extraction at both
ends can be used to implement both, stack and queue
push
pop
enqueue
dequeue
- insert at front
- extract at front
- insert at rear
- extract at front
How to implement
singly / doubly linked lists?
Singly linked list
Easy: take on ordinary list
Doubly linked list
Easy: create a triple-object with selectors left, middle, right
E.g. (define
(make-triple left middle right)
(mcons left (mcons middle right)))
Object Oriented Programming
Is a programming paradigm.
Idea: every problem can be described by objects and their
interactions / relations. This helps creating abstractions
and achieving encapsulation.
Therefore: in order to solve a problem, break it down into
subproblems, by identifying objects and how they interact
with and relate to each other.
OOP Example
Game Pac-Man
Scenario: Pac-Man goes through a
labyrinth, eats pellets and has to avoid
being eaten/attacked by enemies.
Identify Objects:
•
•
•
•
•
Pac-Man
Pellet
Enemy
Power pellet
…
Source: http://en.wikipedia.org/wiki/Pac-Man
OOP Example
Relations between Objects:
•
•
•
•
Pac-Man eats Pellets
Enemy eats/attacks Pac-Man
Pac-Man eats Power pellet
Pac-Man eats Enemy if eaten
recently Power pellet
• …
Source: http://en.wikipedia.org/wiki/Pac-Man
Object Oriented Programming
Is a programming paradigm.
Idea: every problem can be described by objects and their
interactions / relations.
Relations between objects indicate what different
properties the different objects should have.
These properties are realized via fields (variables/data)
and methods (procedures):
Every object has its own fields and methods!
OOP Example
Some fields of some Objects:
Pac-Man:
• Lifes (0-3)
• Score (0-1000000)
• State: recently Power pellet eaten?
• …
Enemy:
• Color
• State: currently eatable or not?
• Direction
• Speed
• …
Source: http://en.wikipedia.org/wiki/Pac-Man
OOP Example
Some methods of some Objects:
Pac-Man:
• (eat-enemy enemy)
• (reduce-life amount)
• (eat-pellet pellet)
• (die)
• …
Enemy:
• (eat-Pac-Man)
• (change-eatable-state value)
• (speed-up)
• (die)
• …
Source: http://en.wikipedia.org/wiki/Pac-Man
OOP Example
Game Pac-Man
Observation:
some objects will occur just once, others several
times
Occurrences of Objects:
•
•
•
•
1x Pac-Man
Nx Pellet
4x Enemy
4x Power pellet
Source: http://en.wikipedia.org/wiki/Pac-Man
OOP Example
Game Pac-Man
Observation:
some objects will occur just once, others several
times
Occurrences of Objects:
•
•
•
•
1x Pac-Man
Nx Pellet
4x Enemy
4x Power pellet
Solution: Classes!
Source: http://en.wikipedia.org/wiki/Pac-Man
OOP - Classes
A Class can be considered as a model for objects that
share the same properties, but are still different
individuals.
If we have a class definition, we can then create an
object from that class.
This process is called instantiating.
For this purpose every class provides a constructor.
OOP Example
Game Pac-Man
Classes for Pac-Man:
•
•
•
•
Pac-Man
Pellet
Enemy
Power-pellet
Then instantiate
•
•
•
•
One object of Pac-Man
Many objects of Pellet
Four objects of Enemy
Four objects of Power-pellet
Source: http://en.wikipedia.org/wiki/Pac-Man
OOP - Inheritance
A Class can be considered as a model for objects that share the
same properties, but are still different individuals.
What if we have similar classes that share a lot of common
properties but are not exactly the same?
Solution: We can derive or inherit a class from another.
Via Inheritance we obtain a derived class, or a subclass.
Think of this as taking a copy of a class, and then modifying this
copy according to our needs.
OOP Example
Game Pac-Man
Similar classes for Pac-Man:
•
•
Pellet
Power-pellet
For instance make Power-pellet a subclass of
Pellet, i.e. treat a Power-pellet as a special case
of a Pellet.
Alternatively: Have a common superclass, call it
General-pellet. Then derive once an Ordinarypellet and once a Power-pellet.
Source: http://en.wikipedia.org/wiki/Pac-Man
OOP in Racket - simple
(define (make-pac-man lifes score pp-eaten) ; three fields
(define (dispatch message . args)
; define different methods
(cond ((eq? message 'eat-enemy)
(if pp-eaten
(void)
'not-possible))
; details to be implemented
((eq? message 'reduce-life)
(set! lifes (- lifes (car args))))
((eq? message 'eat-pellet)
(set! score (+ score 1)))
((eq? message 'die)
(void))
; details to be implemented
((eq? message 'say-hello)
(printf "Hi I am a happy pac-man with ~a lifes\n" lifes))
(else '(unkown message))))
dispatch)
OOP in Racket - simple
(define (make-pac-man lifes score pp-eaten) ; three fields
(define (dispatch message . args)
; define different methods
(cond ((eq? message 'eat-enemy)
(if pp-eaten
; create a Pac-Man: instantiate
(void)
; details to be implemented
(define my-pac-man (make-pac-man 3 0 #f))
'not-possible))
((eq? message 'reduce-life)
; call some
(set! lifes (- lifes (car(my-pac-man
args))))
(my-pac-man
((eq? message 'eat-pellet)
(my-pac-man
(set! score (+ score 1)))
((eq? message 'die)
(void))
methods
'say-hello)
'reduce-life 1)
'say-hello)
Output:
; happy
details
to be with
implemented
Hi I am a
pac-man
3 lifes
Hi I am a happy pac-man with 2 lifes
((eq? message 'say-hello)
(printf "Hi I am a happy pac-man with ~a lifes\n" lifes))
(else '(unkown message))))
dispatch)
OOP in Racket
(define Pac-Man%
(class object%
; fields (variables/data)
(init-field lifes score pp-eaten)
(super-new)
; superclass initialization
(define/public (eat-enemy enemy)
; method
(if pp-eaten
(void)
; details to be implemented
'not-possible))
(define/public (reduce-life amount)
(set! lifes (- lifes amount)))
; method
(define/public (eat-pellet pellet)
(set! score (+ score 1)))
; method
(define/public (die)
; method
(void))
; details to be implemented
(define/public (say-hello)
(printf "Hi I am a happy pac-man with ~a lifes\n" lifes))))
OOP in Racket
(define Pac-Man%
(class object%
; fields (variables/data)
(init-field lifes score pp-eaten)
; create
a Pac-Man: instantiate
(super-new)
; superclass
initialization
(define my-pac-man (make-object Pac-Man% 3 0 #f))
(define/public (eat-enemy enemy)
; method
(if pp-eaten
; call some methods
(void)
; details
tomy-pac-man
be implemented
(send
say-hello)
'not-possible))
(send my-pac-man reduce-life 1)
my-pac-man
say-hello)
(define/public (reduce-life(send
amount)
; method
(set! lifes (- lifes amount)))
Output:
(define/public (eat-pellet pellet)
; method
Hi I am a happy
pac-man with 3 lifes
(set! score (+ score 1)))Hi I am a happy pac-man with 2 lifes
(define/public (die)
; method
(void))
; details to be implemented
(define/public (say-hello)
(printf "Hi I am a happy pac-man with ~a lifes\n" lifes))))
OOP in Racket - Inheritance
(define General-pellet%
(class object%
; fields (variables/data)
(init-field color position)
(super-new)
; superclass initialization
(define/public (get-type)
; method
'general)))
(define Ordinary-pellet%
(class General-pellet%
(super-new)
; superclass initialization
(define/override (get-type)
; method
'ordinary)))
(define Power-pellet%
(class General-pellet%
(super-new)
; superclass initialization
(define/override (get-type)
; method
'power)))
OOP in Racket - Inheritance
(define General-pellet%
(class object%
We inherit from object%
This is a special inbuilt base class
; fields (variables/data)
(init-field color position)
(super-new)
; superclass initialization
(define/public (get-type)
; method
'general)))
(define Ordinary-pellet%
(class General-pellet%
We inherit from General-pellet%
(super-new)
; superclass initialization
(define/override (get-type)
; method
'ordinary)))
(define Power-pellet%
(class General-pellet%
And here too
(super-new)
; superclass initialization
(define/override (get-type)
; method
'power)))
OOP in Racket - Overriding
(define General-pellet%
(class object%
; fields (variables/data)
(init-field color position)
(super-new)
; superclass initialization
(define/public (get-type)
; method
'general)))
(define Ordinary-pellet%
(class General-pellet%
We inherit ALL fields and methods.
That
is:
(super-new)
; superclass
initialization
- no need to redefine ;fields
(define/override (get-type)
methodor methods
- if we want to change a method, we need
'ordinary)))
to explicitly override (redefine) it
(define Power-pellet%
(class General-pellet%
(super-new)
; superclass initialization
(define/override (get-type)
; method
'power)))
OOP in Racket - Instantiation
(make-object <Class> <list of init-values>)
(define my-pac-man
(make-object Pac-Man% 3 0 #f))
; Alternatively:
(new <Class> [varname1 value1] [varname2 value2] ...)
(define my-pac-man
(new Pac-Man%
[lifes 3]
[score 0]
[pp-eaten #f]))
OOP in Racket – calling methods
From inside the class definition you call methods as usual.
From outside special syntax is provided:
(send <object> <method-name> <list of parameters>)
; e.g.:
(send my-pac-man say-hello)
(send my-pac-man reduce-life 1)
(send my-pac-man say-hello)
OOP in Racket – field vs init-field
(define Pac-Man%
(class object%
; init-fields, i.e. values MUST
; be provided during instantiation
(init-field lifes score pp-eaten)
; ordinary fields, i.e. values must be provided
; right here
(field [color 'red] [more-stuff 'hmblhmbl])
...
OOP in Racket – accessing fields
From inside the class definition you access fields as usual variables.
From outside special syntax is provided:
(get-field <field-name> <object-name>)
(set-field! <field-name> <object-name> value)
E.g.
(define my-pac-man (make-object Pac-Man% 3 0 #f))
(get-field color my-pac-man)
(set-field! color my-pac-man 'green)
But: avoid setting fields this way. Better provide your own
methods to change the values of fields.
OOP in Racket – Visibility
public vs private
(define Pac-Man%
(class object%
; public fields (visible/accessible from outside)
(init-field lifes score pp-eaten)
(field [color 'red] [more-stuff 'hmblhmbl])
; private fields (not visible from outside)
(define internal-value 11439)
; public method (visible/accessible from outside)
(define/public (eat-enemy enemy)
; method
(if pp-eaten
(void)
; details to be implemented
'not-possible))
; private method (not visible from outside)
(define (do-some-stuff parameter1)
...)
OOP notions
object, class
field, method
inherit, derive, extend
subclass, superclass
override
OOP purpose
Remember: use OOP in order to create abstractions and to
achieve encapsulation (hide implementation details).
Therefore: keep as much as possible private, so it is not
visible to the outside.
Expose to the outside only what is absolutely necessary.
Provide public methods to manipulate variables/fields, do not
set them directly.
Download