Anda di halaman 1dari 8

Different Views of Object-Oriented System Reminder: Example Class/Instance Diagram

root
• An abstract view
self: z instance
– class and instance diagrams
TYPE
BOOK
– terminology: messages, methods, inheritance, IS-A
is-a self:
superclass, subclass, … name: sicp
superclass NAMED-OBJECT copyright: 1996
• Scheme OO system user view instance-of
name:
– conventions on how to write Scheme code to: TYPE
NAME
• define classes CHANGE-NAME
– inherit from other classes is-a
• create instances subclass BOOK
– use instances (invoke methods) private
copyright:
variables
TYPE
ÎScheme OO system implementer view (under the covers) methods YEAR
– How implement instances, classes, inheritance, types
4/6/2004 1 4/6/2004 2

Implementer’s View of this in Environ. Model Implementer’s View: Instances


(define z (create-book ’sicp 1996)) (define (make-instance)
(let ((handler #f))
GE z: (lambda (message)
(case message
((SET-HANDLER!)
self: self: self: (lambda (handler-proc)
handler: name: sicp name: sicp
copyright:1996 (set! handler handler-proc)))
(else (get-method message handler))))))
named-object- root-part:
p: message part:
body: (case ...)
(define (create-instance maker . args)
BOOK
instance (let* ((instance (make-instance))
p: message p: message p: message (handler (apply maker instance args)))
instance
message handler body: (case ...) body: (case ...) body: (case ...) (ask instance 'SET-HANDLER! handler)
instance))
root
BOOK NAMED-OBJECT message handler
message handler message handler
4/6/2004 3 4/6/2004 4

Implementer’s View: get-method and ask Implementer’s View of this in Environ. Model
Warning! Actual version in Project 4 is
• method lookup: (define z (create-book ’sicp 1996)) slightly different, but has the same
general flavor!!
(define (get-method message object) GE z:
(object message))
self: self: self:
handler: name: sicp name: sicp
• "ask" an object to do something - copyright:1996
combined method retrieval and application to args.
named-object- root-part:
(define (ask object message . args) p: message part:
body: (case ...)
(let ((method (get-method message object)))
BOOK
(if (method? method) instance
(apply method args) instance p: message p: message p: message
message handler body: (case ...) body: (case ...) body: (case ...)
(error "No method for message" message))))

(apply op args)Î(op arg1 arg2 … argn) root


BOOK NAMED-OBJECT message handler
message handler message handler
4/6/2004 5 4/6/2004 6

1
User’s View: Why a “self” variable? Object-Oriented Design & Implementation
• Every class definition has access to a “self” variable • Focus on classes
– self is a pointer to the entire instance
– Relationships between classes
• Why need this? How or when use self ? – Kinds of interactions that need to be supported between
– When implementing a method, sometimes you “ask” a part of instances of classes
yourself to do something
• E.g. inside a BOOK method, we might…
(ask named-object-part ‘CHANGE-NAME ‘mit-sicp) • Careful attention to behavior desired
– However, sometimes we want to ask the whole instance to do – Inheritance of methods
something
• E.g. inside a subclass, we might – Explicit use of superclass methods
(ask self ‘YEAR) – Shadowing of methods to over-ride default behaviors
• This mostly matters when we have subclass methods that
shadow superclass methods, and we want to invoke one of
those shadowing methods from inside the superclass • An extended example to illustrate class design and
implementation
• Next: An example OO design to illustrate our OO system

4/6/2004 7 4/6/2004 8

Person class Person class implementation


PERSON
PERSON (define p1 (create-person 'joe)) (define (create-person name) name:
name: (ask p1 'whoareyou?) (create-instance person name)) TYPE
TYPE ⇒ joe WHOAREYOU?
(define (person self name) SAY
WHOAREYOU?
SAY (ask p1 'say '(the sky is blue)) (let ((root-part (make-root-object self)))
⇒ (the sky is blue) (lambda (message)
(case message
((TYPE) (lambda () (type-extend 'person root-part)))
((WHOAREYOU?) (lambda () name))
((SAY) (lambda (stuff) stuff))
(else (get-method message root-part))))))

4/6/2004 9 4/6/2004 10

Professor class Professor class – with own methods


PERSON (define prof1 (create-professor 'fred)) PERSON (define prof1 (create-professor 'fred))
name: name:
TYPE (ask prof1 'say '(the sky is blue)) TYPE (ask prof1 'whoareyou?)
WHOAREYOU? ⇒ (the sky is blue) WHOAREYOU? ⇒ (prof fred)
SAY SAY
(ask prof1 'lecture '(the sky is blue))
⇒ (therefore the sky is blue)
Is-a Is-a
PROFESSOR PROFESSOR
TYPE TYPE
WHOAREYOU?
LECTURE
A professor’s lecture method will
use the person say method.

4/6/2004 12 4/6/2004 13

2
Professor class implementation Arrogant-Prof class
Is-a
PERSON
PROFESSOR (define ap1 (create-arrogant-prof 'perfect))
(define (create-professor name) name:
(create-instance professor name)) TYPE TYPE (ask ap1 'whoareyou?)
WHOAREYOU? WHOAREYOU? ⇒ (prof perfect)
LECTURE SAY
(define (professor self name)
(let ((person-part (person self name))) (ask ap1 'say '(the sky is blue))
(lambda (message) ⇒ (the sky is blue obviously)
(case message Is-a
((TYPE)
PROFESSOR
(lambda () (type-extend 'professor person-part)))
((WHOAREYOU?) TYPE
(lambda () (list 'prof WHOAREYOU?
(ask person-part 'WHOAREYOU?)))) LECTURE
((LECTURE)
Is-a
(lambda (notes)
(cons 'therefore (ask person-part 'say notes)))) ARROGANT-PROF
(else (get-method message person-part)))))) TYPE
SAY

4/6/2004 14 4/6/2004 15

Arrogant-Prof implementation Arrogant-Prof oddity


Is-a
ARROGANT-PROF PERSON
(define ap1 (create-arrogant-prof 'perfect))
name:
(define (create-arrogant-prof name) TYPE TYPE (ask ap1 'lecture '(the sky is blue))
(create-instance arrogant-prof name)) SAY WHOAREYOU? ⇒ (therefore the sky is blue)
SAY

(define (arrogant-prof self name)


(let ((prof-part (professor self name)))
(lambda (message) Is-a
• Why didn’t arrogant-prof add
(case message PROFESSOR “obviously” at the end?
((TYPE)
(lambda () (type-extend 'arrogant-prof prof-part))) TYPE – Actual source of oddity is in the
WHOAREYOU?
((SAY) (lambda (stuff)
LECTURE professor class, which used SAY
(append (ask prof-part 'say stuff)
(list 'obviously))))
method of person-part
Is-a
(else (get-method message prof-part)))))) ARROGANT-PROF – So the arrogant-professors’ SAY
TYPE method never got used
SAY

4/6/2004 16 4/6/2004 17

Arrogant-Prof oddity corrected Professor class – revised implementation


PERSON Is-a
(define ap1 (create-arrogant-prof 'perfect))
name: (define (create-professor name) PROFESSOR
TYPE (ask ap1 'lecture '(the sky is blue)) (create-instance professor name)) TYPE
WHOAREYOU? ⇒ (therefore the sky is blue obviously) WHOAREYOU?
SAY (define (professor self name) LECTURE
(let ((person-part (person self name)))
(lambda (message)
Is-a (case message
((TYPE)
PROFESSOR
(lambda () (type-extend 'professor person-part)))
TYPE ((WHOAREYOU?) (lambda () (list 'prof name)))
WHOAREYOU? ((LECTURE) (lambda (notes)
LECTURE (cons 'therefore self
(ask person-part 'say notes))))
Is-a
(else (get-method message person-part))))))
ARROGANT-PROF

TYPE
SAY

4/6/2004 18 4/6/2004 19

3
Student class Student implementation
PERSON (define s1 (create-student 'bert)) STUDENT
name: (ask s1 'whoareyou?) TYPE
TYPE ⇒ bert SAY
WHOAREYOU? (define (create-student name)
SAY (create-instance student name))
(ask s1 'say '(i do not understand))
⇒ (excuse me but i do not understand)
(define (student self name)
Is-a (let ((person-part (person self name)))
Is-a
(lambda (message)
PROFESSOR (case message
STUDENT
TYPE ((TYPE)
WHOAREYOU? (lambda () (type-extend 'student person-part)))
LECTURE TYPE ((SAY) (lambda (stuff)
SAY (append '(excuse me but)
Is-a (ask person-part 'say stuff))))
ARROGANT-PROF (else (get-method message person-part))))))
TYPE
SAY

4/6/2004 20 4/6/2004 21

Question and Answer Person class – added methods


PERSON
PERSON (define p1 (create-person 'joe)) name:
name:
(define s1 (create-student 'bert)) (define (person self name) TYPE
TYPE (let ((root-part (root-object self))) WHOAREYOU?
WHOAREYOU? (ask s1 'question p1 (lambda (message) SAY
SAY '(why is the sky blue)) (case message QUESTION
QUESTION ⇒ (bert i do not know about why is the ((TYPE) ANSWER
ANSWER sky blue) (lambda () (type-extend 'person root-part)))
Is-a ((WHOAREYOU?) (lambda () name))
Is-a ((SAY) (lambda (stuff) stuff))
PROFESSOR ((QUESTION)
STUDENT
(lambda (of-whom query) ; person, list -> list
TYPE
WHOAREYOU? (ask of-whom 'answer self query)))
TYPE
LECTURE ((ANSWER)
SAY
(lambda (whom query) ; person, list -> list
Is-a (ask self 'say
ARROGANT-PROF (cons (ask whom 'whoareyou?)
(append '(i do not know about)
TYPE
query)))))
SAY
(else (get-method message root-part))))))
4/6/2004 22 4/6/2004 23

Arrogant-Prof – specialized “answer” Arrogant-Prof: revised implementation


PERSON
(define (arrogant-prof self name)
name: (define s1 (create-student 'bert)) (let ((prof-part (professor self name)))
TYPE (define prof1 (create-professor 'fred)) (lambda (message)
WHOAREYOU? (define ap1 (create-arrogant-prof 'perfect)) (case message
SAY ((TYPE)
QUESTION (ask s1 'question ap1 (lambda () (type-extend 'arrogant-prof prof-part)))
ANSWER
'(why is the sky blue)) ((SAY) (lambda (stuff)
⇒ (this should be obvious to you obviously) (append (ask prof-part 'say stuff)
Is-a
PROFESSOR (list 'obviously))))
(ask prof1 'question ap1 ((ANSWER)
TYPE '(why is the sky blue)) (lambda (whom query)
WHOAREYOU? ⇒ (but you wrote a paper about why (cond ((ask whom 'is-a 'student)
LECTURE is the sky blue obviously) (ask self 'say
Is-a '(this should be obvious to you)))
((ask whom 'is-a 'professor)
ARROGANT-PROF
(ask self 'say
TYPE (append '(but you wrote a paper about)
SAY query)))
ANSWER (else (ask prof-part 'answer whom query)))))
(else (get-method message prof-part))))))
4/6/2004 24 4/6/2004 25

4
Lessons from our example class hierarchy Steps toward our Scheme OOPS:
• Specifying class hierarchies • Basic Objects
– Convention on the structure of a class definition – messages and methods convention
• to inherit structure and methods from superclasses – self variable to refer to oneself
• Control over behavior
• Inheritance
– Can “ask” a sub-part to do something
– internal parts to inherit superclass behaviors
– Can “ask” self to do something
– in local methods, can “ask” internal parts to do
• Use of TYPE information for additional control something
– use get-method on superclass parts to find method if
needed

• Multiple Inheritance Í

4/6/2004 26 4/6/2004 27

A Singer, and a Singing-Arrogant-Prof Singer implementation


PERSON
(define (create-singer)
name: A singer is not a person. (create-instance singer)) SINGER
TYPE
WHOAREYOU?
SAY
A singer has a different SAY that (define (singer self) TYPE
SAY
QUESTION always ends in "tra la la". (let ((root-part (root-object self)))
SING
ANSWER (lambda (message)
A singer starts to SING with "the (case message
Is-a ((TYPE)
hills are alive" (lambda () (type-extend 'singer root-part)))
PROFESSOR SINGER
((SAY)
TYPE TYPE (lambda (stuff) (append stuff '(tra la la))))
WHOAREYOU? SAY ((SING)
LECTURE SING (lambda () (ask self 'say '(the hills are alive))))
Is-a is-a is-a (else (get-method message root-part))))))
ARROGANT-PROF
S-A-P
TYPE • The singer is a "base" class (its only superclass is root)
SAY
ANSWER

4/6/2004 28 4/6/2004 29

Singing-Arrogant-Prof implementation Example: A Singing Arrogant Professor


ARROGANT- (define sap1 (create-singing-arrogant-prof 'zoe))
PROF SINGER
(ask sap1 'whoareyou?)
⇒ (prof zoe)
(define (create-singing-arrogant-prof name) S-A-P (ask sap1 'sing)
(create-instance singing-arrogant-prof name)) ⇒ (the hills are alive tra la la)

(define (singing-arrogant-prof self name) (ask sap1 'say '(the sky is blue))
(let ((singer-part (singer self)) ⇒ (the sky is blue tra la la)
(arr-prof-part (arrogant-prof self name)))
(ask sap1 'lecture '(the sky is blue))
(lambda (message)
⇒ (therefore the sky is blue tra la la)
(case message
((TYPE)
(lambda () (type-extend 'singing-arrogant-prof • See that arrogant-prof’s SAY method is never used in sap1 (no
singer-part “obviously” at end)
arr-prof-part))) – Our get-method passes the SAY message along to the singer class
(else (get-method message singer-part first, so the singer’s SAY method is found
arr-prof-part)))))) • If we needed finer control (e.g. some combination of SAYing)
– Then we could implement a SAY method in singing-arrogant-prof
class to specialize this behavior
4/6/2004 30 4/6/2004 31

5
Implementation View: Multiple Inheritance Summary
• How implement the more general get-method? • Classes: capture common behavior
– Just look through the supplied objects from left to right • Instances: unique identity with own local state
until the first matching method is found.
(define (get-method message object) • Hierarchy of classes
(object message)) – Inheritance of state and behavior from superclass
becomes – Multiple inheritance: rules for finding methods
(define (get-method message . objects)
(define (try objects) • Object-Oriented Programming Systems (OOPS)
(if (null? objects)
– Abstract view: class and instance diagrams
(no-method)
(let ((method ((car objects) message))) – User view: how to define classes, create instances
(if (not (eq? method (no-method))) – Implementation view: how we layer notion of object
method classes, instances, and inheritance on top of standard
(try (cdr objects)))))) Scheme
(try objects))
4/6/2004 32 4/6/2004 33

OOPS – One more example Some Classes for Family Relationships

• Goal: See an example that distinguishes between


– “is-a” or inheritance relationships ROOT-OBJECT • Look at these classes (named-object,
– “has-a” or local variable relationships is-a person, mother) from perspectives of
NAMED-OBJECT – class diagrams
• Idea: is-a – desired behaviors
– A person class with parent-child relationships PERSON – instance diagrams
is-a – our class/method definitions
MOTHER – underlying representation
(environment model)

4/6/2004 34 4/6/2004 35

Named-object class definition Some Family Relationships – Class Diagram


ROOT-OBJECT NAMED-OBJECT
(define (create-named-object name) is-a is-a • person inherits from named-object
(create-instance named-object name)) NAMED-OBJECT PERSON • local state: a person now…
name: mother: has-a
(define (named-object self name)
has-a
– has-a mother (of type mother)
(let ((root-part (root-object self))) father:
TYPE
children: has-a list of – has-a father (of type person)
(lambda (message) NAME
(case message – has-a list of children (of type
TYPE
((TYPE) SAY person)
(lambda () (type-extend 'named-object root-part))) MOTHER
((NAME) (lambda () name))
• additional person methods to
SET-MOTHER!
(else (get-method message root-part)))))) FATHER manage state
SET-FATHER! • a mother inherits from person
(define (names-of objects) ADD-CHILD
; Given a list of objects, returns a list of their names. CHILDREN – adds the have-child method
(map (lambda (x) (ask x 'NAME)) objects)) is-a
MOTHER

• Very simple state and behavior: a local name, TYPE


which the user can access through NAME method. HAVE-CHILD

4/6/2004 36 4/6/2004 37

6
Some Family Relationships – Behaviors Some Family Relationships – Instance Diagram
NAMED-OBJECT
is-a (define a (create-mother 'anne)) a
(define b (create-person 'bob))
PERSON (ask a 'name) ;Value: anne MOTHER
mother: has-a (ask b 'name) ;Value: bob c
name: anne
father: has-a (ask a 'type)
mother: nil
children:
;Value:
has-a list of (mother person named-object root) PERSON
father: nil
father name: cindy children:
(ask b 'type) mother
TYPE mother:
SAY ;Value: (person named-object root) father:
MOTHER children: nil
SET-MOTHER! (define c (ask a 'have-child b 'cindy))
FATHER (define d (ask a 'have-child b 'dan)) b
SET-FATHER! (names-of (ask a 'children)) d
ADD-CHILD ;Value: (dan cindy) PERSON
CHILDREN PERSON name: bob
(names-of (ask b 'children))
is-a name: dan mother: nil
;Value: (dan cindy)
mother: father: nil
MOTHER
(ask d 'name) ;Value: dan father: children:
TYPE (ask (ask d 'mother) 'name) ;Value: anne children: nil
HAVE-CHILD

4/6/2004 38 4/6/2004 39

NAMED-OBJECT
Person Class Definition is-a Mother Class Definition
(define (create-person name) PERSON
(create-instance person name)) mother: PERSON
father:
is-a
(define (person self name)
children: (define (create-mother name)
TYPE (create-instance mother name)) MOTHER
(let ((named-part (named-object self name))
SAY
(mother nil) MOTHER TYPE
(father nil) SET-MOTHER! (define (mother self name) HAVE-CHILD
(children nil))
FATHER (let ((person-part (person self name)))
SET-FATHER!
(lambda (message) ADD-CHILD (lambda (message)
CHILDREN (case message
(case message
((TYPE) (lambda () (type-extend 'person named-part))) ((TYPE) (lambda () (type-extend 'mother person-part)))
((SAY) (lambda (stuff) (display stuff))) ((HAVE-CHILD)
((MOTHER) (lambda () mother)) (lambda (dad child-name)
((FATHER) (lambda () father)) (let ((child (create-person child-name)))
((CHILDREN) (lambda () children)) (ask child 'set-mother! self)
((SET-MOTHER!) (lambda (mom) (set! mother mom))) (ask child 'set-father! dad)
((SET-FATHER!) (lambda (dad) (set! father dad))) (ask self 'add-child child)
((ADD-CHILD) (lambda (child) (ask dad 'add-child child))))
(set! children (cons child children)) (else (get-method message person-part))))))
child))
(else (get-method message named-part))))))
4/6/2004 40 4/6/2004 41

Some Family Relationships – Instance Diagram Some Family Relationships – Instance Diagram
(define a (create-mother 'anne))
a a
(define b (create-person 'bob))
MOTHER MOTHER
child
name: anne name: anne
mother: nil mother: nil
PERSON
father: nil father: nil
children: name: cindy children:
mother:
father:
children: nil

b b

PERSON PERSON
name: bob name: bob
(lambda (dad child-name) mother: nil (lambda (dad child-name) mother: nil
(let ((child (create-person child-name))) father: nil (let ((child (create-person child-name))) father: nil
(ask child 'set-mother! self) children: (ask child 'set-mother! self) children:
(ask child 'set-father! dad) (ask child 'set-father! dad)
(ask self 'add-child child) (ask self 'add-child child)
(ask dad 'add-child child))) (ask dad 'add-child child) ))

4/6/2004 42 4/6/2004 43

7
Result of Result of (define (make-person self name)
(let ((named-part (make-named-object self name))
(create-person ‘cindy) => (create-person ‘cindy) =>(mother nil)
(create-instance make-person ‘cindy) (create-instance make-person
(father‘cindy)
nil)
(children nil))
(lambda (message)
GE GE (case message …))))
c: c:

(define (make-instance)
(let ((handler #f)) self:
(lambda (message) name: cindy
(case message
handler: ((SET-HANDLER!) handler:
(lambda (handler-proc) mother: nil
(set! handler handler-proc))) father: nil
(else (get-method message handler)))) )) children: nil
p: message p: message named-part:
(define (create-instance maker . args)
body: (case ...) body: (case ...)
(let* ((instance (make-instance) )
PERSON (handler (apply maker instance args) )) PERSON (define (create-instance maker . args)
instance (ask instance 'SET-HANDLER! handler) instance (let* ((instance (make-instance) )
instance)) (handler (apply maker
p: message
instance instance body: (case ...) instance args) ))
message handler message handler (ask instance 'SET-HANDLER! handler)
instance))
PERSON
message handler
4/6/2004 44 4/6/2004 (from make-person) 45

Result of (define (make-named-object self name) Result of (define (make-named-object self name)
(let ((root-part (make-root-object self))) (let ((root-part (make-root-object self) ))
(create-person ‘cindy) =>
(lambda (message)
(create-person ‘cindy) =>
(lambda (message)
(create-instance make-person ‘cindy)
(case message …)))) (create-instance make-person ‘cindy)
(case message …))))

GE c:
GE c:

self: self: self: self: self:


name: cindy name: cindy name: cindy name: cindy

handler: handler:
mother: nil root-part: mother: nil root-part:
father: nil father: nil
children: nil children: nil
p: message named-part: p: message named-part:
body: (case ...) body: (case ...)

PERSON p: message PERSON p: message p: message


instance body: (case ...) instance body: (case ...) body: (case ...)
p: message p: message
instance body: (case ...) instance body: (case ...)
message handler message handler
root
PERSON NAMED-OBJECT PERSON NAMED-OBJECT message handler
message handler message handler message handler message handler
4/6/2004 (from make-person) 46 4/6/2004 (from make-person) 47

Result of
(ask c ‘name)
2. Person handler does not
have ‘NAME method;
Summary
3. Named-object handler
calls get-method on
finds NAME method
1. Calls get-method on handler
named-part • Classes in our system
– May have local state and local methods. Local state can:
• include primitive data (e.g. a name symbol)
• indicate relationships with other objects (e.g. pointers
self: self: self:
name: cindy name: cindy
to other instances in the system)
– May inherit state and methods
handler:
mother: … root-part: • By way of internal handlers generated thru “make-
father: … <superclass>” parts
children: nil
p: message named-part: • Instances in our system
body: (case ...)
– Have a starting “instance” (self) object in env. model
p: message p: message
body: (case ...) body: (case ...) – Instance contains a series of message/state handlers for
p: message
E1: message: name
each class in inheritance chain
body: (case ...)
– You need to gain experience with this!
4. (lambda () name) | E1 Î #[proc 9] E2:
5. (#[proc 9]) | E55 Î name | E2 Î cindy p: name | E2
4/6/2004 48 4/6/2004 49
body: name