73
1 Object-Oriented Programming

1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

Embed Size (px)

Citation preview

Page 1: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

1

Object-Oriented Programming

Page 2: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

2

Object-Oriented Programming = Abstract Data Types

package representation of data structure together with operations on the data structure

encapsulate internal implementation details + Inheritance

support defining new ADT as incremental change to previous ADT(s)

share operations across multiple ADTs + Subclass Polymorphism

allow variables to hold instances of different ADTs + Dynamic Binding

run-time support for selecting right implementation of operation, depending on argument(s)

Page 3: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

3

Some OO languages Simula 67: the original Smalltalk-80: popularized OO C++: OO for the hacking masses Java, C#: cleaned up, more portable

variants of C++ CLOS: powerful OO part of Common Lisp Self: very pure OO language Cecil, MultiJava, EML: OO languages

from my research group Emerald, Kaleidoscope: other OO

languages from UW

Page 4: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

4

Abstract data types User-defined data structures along with user-

defined operations Support good specification of interface to ADT, hiding

distracting implementation details Prevent undesired dependencies between client and

ADT, allowing implementation to change w/o affecting clients

Allow language to be extended with new types, raising & customizing the level of the language

Called a class in OO languages data structures called objects, or instances of the class operations called methods; data called instance

variables Modules have similar benefits

Page 5: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

5

Inheritance Most recognizable aspect of OO languages &

programs Define new class as incremental modification

of existing class new class is subclass of the original class (the

superclass) by default, inherit superclass’s methods & instance

vars can add more methods & instance vars in subclass can override (replace) methods in subclass

but not instance variables, usually

Page 6: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

6

Exampleclass Rectangle {

Point center;int height, width;int area() { return height * width; }void draw(OutputDevice out) { ... }void move(Point new_c) { center = new_c; }...

}class ColoredRectangle extends Rectangle {

// center, height, & width inheritedColor color;// area, move, etc. inheritedvoid draw(OutputDevice out) { ... } // override!

}

Page 7: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

7

Benefits of inheritance Achieve more code sharing by factoring code

into common superclass superclass can be abstract

no direct instances, just reusable unit of implementation

encourages development of rich libraries of related data structures

May model real world scenarios well use classes to model different things use inheritance for classification of things:

subclass is a special case of superclass

Page 8: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

8

Pitfalls of inheritance Inheritance often overused by

novices Code gets fragmented into small

factored pieces Simple extension & overriding may

be too limited e.g. exceptions in real-world

classification hierarchies

Page 9: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

9

Subclass polymorphism Allow instance of subclass to be used wherever

instance of superclass expected client code written for superclass also works/is

reusable for all subclasses

void client(Rectangle r) {… r.draw(screen) …

}

ColoredRectangle cr = ...;… client(cr) …// legal, because ColoredRectangle is a subclass of Rectangle

// but what version of draw is invoked?

Page 10: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

10

Dynamic binding When invoke operations on object, invoke

appropriate operation for dynamic class of object, not static class/type

ColoredRectangle cr = …;Rectangle r = cr; // OK, because CR subclass of R

r.draw();   // invokes ColoredRectangle::draw!

Also known asmessage passing,virtual function calling,generic function application

Page 11: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

11

Method lookup Given a message obj.msg(args) …

Start with run-time class C of obj(the receiver) if msg is defined in C, then invoke it otherwise, recursively search in superclass

of C if never find match, report run-time error

type checker guarantees this won’t happen

Page 12: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

12

Dynamic dispatching vs.static overloading Like overloading:

multiple methods with same name, in different classes use class/type of argument to resolve to desired

method Unlike overloading:

resolve using run-time class of argument,not static class/type

consider only receiver argument, in most OO languages C++ & Java: regular static overloading on arguments, too CLOS, Cecil, MultiJava: resolve using all arguments

(multiple dispatching)

Page 13: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

13

Example Without dynamic binding, use "typecase" idiom:

forall Shape s in scene.shapes doif s.is_rectangle() then rectangle(s).draw();else if s.is_square() then square(s).draw();else if s.is_circle() then circle(s).draw();else error(“unexpected shape”);end

end With dynamic binding, send message:

forall Shape s in scene.shapes dos.draw();

end What happens if a new Shape subclass is added?

Page 14: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

14

Benefits of dynamic binding Allows subclass polymorphism and dynamic

dispatching to class-specific methods Allows new subclasses to be added without

modifying clients Allows more factoring of common code into

superclass, since superclass code can be “parameterized” by “sends to self” that invoke subclass-specific operations

"Template method" design pattern

Page 15: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

15

Pitfalls of dynamic binding Tracing flow of control of code is

harder control can pop up and down the class

hierarchy

Adds run-time overhead space for run-time class info time to do method lookup

but only an array lookup (or equivalent),not a search

Page 16: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

16

Issues inobject-oriented language design Object model:

hybrid vs. pure OO languages class-based vs. classless (prototype-based)

languages single inheritance vs. multiple inheritance

Dispatching model: single dispatching vs. multiple dispatching

Static type checking: types vs. classes subtyping subtype-bounded polymorphism

Page 17: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

17

Self

Page 18: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

18

Self A purely object-oriented language,

developed as a Smalltalk successor in 1986/7 Every thing is an object

including primitives like numbers, booleans, etc. no classes, only prototypes first-class functions (aka blocks) are objects even methods are objects

Every action is a message operations on primitives control structures access & assignment to instance variables

Scoping is inheritance Theme: simplicity (uniformity) yields power

Page 19: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

19

Self objects An object is just a list of slots

A slot is a key/value pair The contents of a slot is (a reference to)

another object Example: (| x = 3. y = 4. |)

x

y

3

4

Page 20: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

20

Accessing slots The only thing you can do with an

object is send it a message To fetch the contents of an object's

slot, send the slot's name as a message to the object

Example:let aPoint = ( | x = 3. y = 4. | )

aPoint x "send x to aPoint, yielding 3"

Page 21: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

21

Methods A method is just a special kind of object

stored in a slot Special because it has code that runs when it's

looked up in a slot Example:

let aPoint =

( | x = 3.

y = 4.

distanceToOrigin = ((self x squared + self y squared) sqrt

)

| )

aPoint distanceToOrigin "yields 5"

Page 22: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

22

Syntax of messages Unary messages: a simple identifier written after the

receiver right-associative

aPoint distanceToOrigin self x self x squared (…) sqrt

Binary messages: punctuation symbol(s) written between its two arguments

any sequence of punctuation symbols allowed; user-defined operators

lower precedence than unary messages all binary messages have same precedence and are left-

associative x squared + y squared 3 + 4 * 5 yields 35

Keyword messages: later…

Page 23: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

23

Sends to self In a method, the name of the receiver of

the message is self If no receiver specified, then it's

implicitly self E.g.

self x squared can be written x squared distanceToOrigin = (

(x squared + y squared) sqrt )

Makes method calls as concise as (traditional) instance variable access

Page 24: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

24

Making new objects Can make new objects by:

writing them down explicitly (as we've done), or cloning an existing object (the prototype)

a shallow copy of the object

Example:let otherPoint = aPoint clone.

x

y

3

4d2o

(…) sqrt

x

y

d2o

Page 25: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

25

Mutable slots Slots initialized with = are immutable Slots initialized with <- are mutable To change a slot named x, send the object the x: message with the new value returns the receiver, e.g. for additional updates

Example:let aPoint = (| x <- 3. y <- 4. |).

aPoint x: 5. "updates aPoint's x slot to refer to 5"aPoint x "yields 5"aPoint y: aPoint y + 1. "increments y"(aPoint x: 0) y: 0. "sets aPoint to be the origin"

Page 26: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

26

Assignment slots When a mutable slot named x is declared, two

slots are created in the object: one named x referring to the slot's (current) contents one named x: referring to the assignment primitive

Example: (| x <- 3. y <- 4. |)

x: <-

y

3

4

x

y: <-

Page 27: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

27

Keyword messages A keyword message is an identifier

followed by a colon It takes an argument after the colon aPoint x: 5

The message is x: The receiver is (the result of evaluating) aPoint The argument is (the result of evaluating) 5

Also have keyword messages that can take more than one argument (later…)

Page 28: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

28

Methods with arguments A method object can take one or more

arguments by declaring slots whose names begin with colons One argument slot for each argument that can be

accepted according to the slot name 1 for binary messages 1 or more for keyword messages

Example:(| …

+ = (| :p | (clone x: x + p x) y: y + p y )

|)

Shorthand: put argument name in slot name + p = ( (clone x: x + p x) y: y + p y )

Page 29: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

29

A scenario… We define the first point as

let aPoint =

( | x = 3.

y = 4.

distanceToOrigin = ( … )

+ p = ( … )

… "lots of other methods on points" | )

Then we make lots of other points via cloning… aPoint clone … p3 + p9 …

Then we want to add a new method to all points how?

Page 30: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

30

Inheritance Introduce sharing through inheritance Put shared slots (e.g. methods) into one

object (called a traits object) Put object-specific slots (e.g. instance vars)

into another object (called a prototype object)

Have the prototype inherit the traits By adding a slot marked as a parent slot using an

asterisk Clone the prototype to make new objects

They'll also inherit the same traits object

Page 31: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

31

Examplelet pointTraits =

( | distanceToOrigin = ( … )

+ p = ( … )

… "lots of other methods on points" | )

let pointProto =( | x <- 0. "default initial coordinates" y <- 0.

parent* = pointTraits. "inherit shared code" | )

let p1 = (pointProto clone x: 3) y: 4.

Page 32: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

32

The result

(…) sqrtd2o

+

… clone …

x: <-

y

x

y: <-

parent

x: <-

y

x

y: <-

parent

3

4

0

0

pointTraits

pointProto p1

Page 33: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

33

Message lookup, revisited If a message msg is sent to an object:

If the object contains a slot named msg, get the object referenced by the slot

If it's the assignment primitive, do an assignment to the corresponding data slot

If it's a method, run its body and return the result (more later)

Otherwise, just return the contents Otherwise, look for a slot marked as a parent

slot If found, then recursively look up the message in the

object referred to by the parent slot(Parents can contain their own parent slots, etc.)

Otherwise, report a "message not understood" error

Page 34: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

34

Invoking a method To run a method object:

Clone the method object to make a method activation object

a stack frame! Initialize the argument slots of the

cloned method to the argument objects Evaluate the expression(s) in the body Return the result of the last expression

But what about self?

Page 35: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

35

Self self is an implicit argument slot of

every method What is the self argument?

The original object that received the message?

Or the object containing the method? Or something else?

Consider a message p1 + p1; in the + method inherited from pointTraits, what's self bound to?

Page 36: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

36

Local slots Methods can have slots

E.g. argument slots Plus regular slots which act like local variables

Sends to implicit self actually start the message lookup in the currently executing method activation object The self slot of the method is a parent slot, so

that lookup continues to search the receiver if a message to implicit self doesn't match a local slot

The method activation is a refinement of the receiver Example:

+ = (| ":self*" :p | … x + p x … )

Page 37: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

37

Multiple arguments To send a message with multiple arguments,

use extended keyword messages Interleave keyword message part with argument

expressions In Self, the first keyword message part must start

with a lower-case letter; the rest must start with an upper-case letter

Example: pointTraits newX: x Y: y

message/slot name: newX:Y: receiver: pointTraits arguments: x and y

pointTraits = (| newX: x Y: y = ( … ). … |)

Page 38: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

38

Summary, so far Saw syntax & semantics of declaring

objects, sending messages, inheritance, assignment

Didn't see classes… Didn't see constructors… Didn't see static methods & variables vs.

instance methods & variables… Didn't see different syntax for accessing

instance variables vs. calling methods…

Page 39: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

39

What do classes usually offer? Can define the methods and instance variables of its

instances Self lets each object be self-sufficient & self-describing Self programmers use shared traits objects as a way to share

things across all instances of a class (Doesn't work as well for instance variables)

Can inherit from other classes Self allows individual objects to inherit directly from other objects

Self inheritance is used for both class inheritance and class instantiation

Can have static/class methods and instance variables Self programmers can define separate objects (e.g. factories) if

they want these things Can define constructors

Self programmers define regular methods which use clone to do this

Page 40: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

40

Benefits of prototype model Self is much simpler by not having separate

class and instance concepts Also:

makes singleton objects natural avoids the problem of "what's the class of a

class? and what's its class? and …" no metaclasses

allows instances to inherit run-time state from other instances

allows inheritance to be changed at run-time, by making parent slots assignable

called dynamic inheritance

Page 41: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

41

Benefits of uniform messaging Traditionally, instance variables and

methods are accessed differently Self accesses them both via messages

Easy to change implementation from data to code or vice versa, without affecting clients

Easy to override data, and override code with data

Still syntactically concise C#'s attributes are a clumsy version of

this

Page 42: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

42

Benefits of uniform objects Primitive values are first-class objects

Inherit from predefined traits objects, etc., for their behavior

Send them messages just like other objects To make this work using expected syntax,

syntax of "operations" are available to all objects

Can add user-defined methods on them, just like other objects

Page 43: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

43

First-class functions Self includes first-class functions as objects

Called "blocks" Written like a method, except use [ … ]

instead of ( … ) Invoke a block by sending it the value

message (or value: if it takes an argument, or value:With:With: if it takes 3 arguments) [| :arg1. :arg2 | code ] means(| value: arg1 With: arg2 = ( code ) |)

Page 44: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

44

Lexical scoping Blocks can be nested in methods

Can access slots of lexically enclosing method

Implemented by giving block activation objects an implicit anonymous parent slot that inherits from the lexically enclosing method activation object

Lexical scoping is just inheritance!

Page 45: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

45

Control structures using blocks Self has no built-in control structures Instead, use objects, messages, and

blocks to program them all, entirely in (extensible) user code

Example:let true =(| parent* = boolTraits. ifTrue: trueBlock False: falseBlock = ( trueBlock value ) |)

let false = (| … falseBlock value … |)

(x < 0) ifTrue: ['neg'] False: ['non-neg']

Page 46: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

46

Iterators To preserve abstraction of

collections, each defines one (or more) iterator methods

Most basic: do: aList do: [ |:elem| elem print. ].

Others: keysAndValuesDo:, includes:, includesKey:, filterBy:, map:, …

Page 47: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

47

Example: association listlet assocListTraits = (|

parent* = orderedCollectionTraits. "lots of cool methods"assoc = (| key. value. next. |). "implicit <-nil"assocsDo: aBlock = (

| assoc <- head |[assoc != nil] whileDo: [

aBlock value: assoc. assoc: assoc next. ] ).

keysAndValuesDo: aBlock = (assocsDo: [|:assoc| aBlock value: assoc key With: assoc value] ).

|).at: k Put: v = ( "should check for existing assoc, too"

assocsDo: [|:assoc| (assoc key = k) ifTrue: [ assoc value: v. ^self ] ]. "^ does early

return"head: ((assoc clone key: k) value: v) next: head. ).

let assocListProto = (| parent* = assocListTraits. head. |).

Page 48: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

48

A clientlet phoneBook = assocListProto clone.

phoneBook at: 'Sylvia' Put: '123-4567'.

phoneBook at: 'Andrei' Put: 'unlisted'.

phoneBook keysAndValuesDo: [|:name. :number|

('calling ' + name + '...').print.

number makeCrankCall.

].

Page 49: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

49

Top-level environment There's a distinguished object that's

the top-level environment It defines or inherits slots for all

"global" names, e.g. pointTraits, assocListProto, …

A Self read-eval-print interpreter executes expressions in the context of this object It's the implicit self of the read-eval-print

loop

Page 50: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

50

Updating existing objects Introduce (true) primitives to modify

existing objects obj _AddSlots: (| slots |)

adds slots to obj, replacing any that already exist

obj _DefineSlots: (| slots |) like _AddSlots:, plus removes all others from obj

No need for special let construct let pointTraits = (|…|) is really_AddSlots: (| pointTraits = (|…|) |)

Page 51: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

51

Cecil

Page 52: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

52

Cecil Inspired by Self:

A classless object model Uniform use of messages for everything

Inspired by CLOS: Multiple dispatching

Extends both OO and functional programming styles

Inspired by Trellis: Static typechecking Optional

Support mixing dynamically and statically typed code

Page 53: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

53

Bindings Use let to define (local and global)

variables add var keyword to allow assignment,

otherwise immutable must initialize at declaration

let inc := 1;

let var count := 0;

count := count + inc;

Page 54: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

54

Functions Use method to define functions

last expression evaluated is returned can overload name for different numbers of

argumentslet var count := 0;

method foo(a, b, c) {count := count + 1;let var d := a + b;let e := frob(d, c);d := d + e;d + 5 }

method frob(x, y) { x - frob(y) + 1 }

method frob(x) { - x / 5 }

Page 55: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

55

Closures: first-class functions Code bracketed in braces is a 0-argument

function valuelet closure := { factorial(10) + 5 };

Evaluation of closure body delayed until invoked by eval:

eval(closure)   3628805 To allow arguments to closure, add &(x,y,z)

prefix;invoke passing extra arguments to eval:

let closure2 := &(n){ factorial(n) + 5 };

...eval(closure2, 10)   3628805

Like ML's fn, Self's blocks: anonymous, lexically scoped, first-class

Page 56: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

56

Glitch: returning closures In current Cecil implementation,

by default,closures cannot safely be returned out of theirlexically enclosing scope a glitch in the Vortex

implementation, not the Cecil language

can crash Vortex mysteriously prevents currying, compose,

closures in data structures, ...

Page 57: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

57

Avoiding the glitch To be able to return closures, use && rather than &:

method add_x(x) { &&(y){ x + y } }

let add_2 := add_x(2);

let add_5 := add_x(5);

eval(add_2, 4)    6eval(add_5, 4)    9

Page 58: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

58

Using closures in control structures As in Self, all traditional (and many

non-traditional) control structures are implemented as regular Cecil functions, with closures passed by callers supporting the necessary evaluation-only-on-demand

For simple lazy or repeated evaluation:if(test, { then_value }, { else_value })

test1 & { test2 }while({ test }, { body })

Page 59: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

59

More examples For iteration with arguments:

for(start, stop, &(i){ body })

do(array, &(elem){ body })

do_associations(table,

&(key,value){ body })

For exception handling:fetch(table, key, { if_absent })

For 3-way branching:compare(i, j, {if_lt}, {if_eq}, {if_gt})

Page 60: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

60

An example-- this is a factorial method

method factorial(n) {

if(n = 0,

   { 1 },

   { n * factorial(n - 1) }) }

-- call factorial here:

factorial(7)

Page 61: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

61

Non-local returns Support exiting a method early

with a non-local return from a nested closure like ^ in Self like a return statement in C

{ ...; ^ result }

{ ...; ^ } -- return void

Page 62: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

62

Examplemethod fetch(table, key, if_absent) {do_associations(table, &(k, v){ if(k = key, { ^ v });});eval(if_absent) }

method fetch(table, key) {fetch(table, key, { error("key " || print_string(key) ||    " not found") }) }

fetch(zips, "Seattle", { 98195 })

Page 63: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

63

Objects To define a new kind of ADT, use an object declaration

object Point;

No classes! To make a new "instance" of that

ADT, use an object isa … expression

method new_point() {object isa Point }

No special constructors!

Page 64: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

64

Methods of objects To define a method "in" an object,

write the method outside the object but specialize the method to the object by adding @obj after the first argument (which acts like the receiver argument)

method area(p@Point) {p.x * p.y }

method shift(p@Point, dx, dy) {p.x := p.x + dx;p.y := p.y + dy; }

Page 65: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

65

Fields of objects To declare an instance variable, use a field

declaration specialize the field to the object "containing" the field add var keyword to allow assignment, otherwise

immutable fields can be given default initial values at declaration fields can be given initial values at object creation

supports immutable, initialized fields!

var field x(p@Point) := 0;var field y(p@Point) := 0;method new_point(x0, y0) {object isa Point { x := x0, y := y0 } }

Page 66: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

66

Fields accessed by messages Field declarations implicitly produce 1 or 2

accessor methods: get accessor: given object, return field contents set accessor (for var fields): given object & field’s new

contents, modify field Manipulate field contents solely by invoking

these methodsvar field x(p@Point) := 0;

method x(p@Point) { ... fetch p.x’s contents,

initially 0 ...}method set_x(p@Point,

new_value) { ... update p.x to be

new_value ... }

-- increment p.x:set_x(p, x(p) + 1)

Page 67: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

67

Syntactic sugar For syntactic convenience, any call

can be written using dot notation:p.x              x(p)

p.x := p.x + 1   set_x(p,x(p)+1)

p.shift(3,4)     shift(p, 3, 4)

Infix & prefix operators (e.g. +) are really messages, too

Page 68: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

68

Inheritance Make new ADTs from old ones via isa inheritance link

object ColoredPoint isa Point;

child/parent, a.k.a. subclass/superclass inherit all method & field declarations can add new methods & fields,

specialized on child object can override methods & fields

Page 69: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

69

Exampleobject ColoredPoint isa Point;

-- inherit all Point fields and methods-- add some new ones:field color(cp@ColoredPoint);

method new_colored_point(x0, y0, c0) {object isa ColoredPoint { x := x0, y := y0, color := c0 } }

let p := new_colored_point(3,4,"Blue");

print(p.color);   "Blue"p.shift(2,-2); -- invoke inherited

methodprint(p.x);       5

Page 70: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

70

Overriding of methods Child can override inherited method by

defining its ownobject Point;method draw(p@Point) { … }

object ColoredPoint isa Point;method draw(p@ColoredPoint) { … }

let p := new_point(3,4);p.draw;   -- invoke's Point’s draw

let cp := new_colored_point(5,6,"Red");

cp.draw;  -- invokes ColoredPoint's draw

Page 71: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

71

Overloaded methods and dynamic dispatching Can overload methods two ways:

same name but different numbers of arguments

same name & number of arguments,but different specializer objects

Specializer-based overloading resolved by using run-time class of receiver argument(a.k.a. dynamic dispatching, message sending)

Page 72: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

72

Multimethods Any argument, not just the receiver, can be

specialized to an object

method =(p1@Point, p2@Point) {p1.x = p2.x & { p1.y = p2.y } }

method =(cp1@ColoredPoint, cp2@ColoredPoint){

cp1.x = cp2.x & { cp1.y = cp2.y } &

{ cp1.color = cp2.color } }

A message invokes theunique most-specific applicable method

Page 73: 1 Object-Oriented Programming. 2 = Abstract Data Types package representation of data structure together with operations on the data structure encapsulate

73

Method lookup rules Find all methods with the right name and number of

arguments that apply A method applies if the actual run-time objects are equal

to or inherit from all the method's specializers, where present

Report "message not understood" if no applicable methods Pick the applicable method whose specializers are

uniformly most specific A specializer is more specific than another if it inherits

from the other A method overrides another if all of its specializers are at

least as specific as the other's Report "message ambiguous" if no single best method