Case Study: The Number Hierarchy Goal: Develop feel for programming - - PowerPoint PPT Presentation

case study the number hierarchy
SMART_READER_LITE
LIVE PREVIEW

Case Study: The Number Hierarchy Goal: Develop feel for programming - - PowerPoint PPT Presentation

Case Study: The Number Hierarchy Goal: Develop feel for programming in the large Issues well consider along the way: Class design What methods go where? Invariants Class methods establish invariants Instance methods


slide-1
SLIDE 1

Case Study: The Number Hierarchy

Goal: Develop feel for programming in the large Issues we’ll consider along the way:

  • Class design

– What methods go where?

  • Invariants

– Class methods establish invariants – Instance methods must maintain them

  • Information hiding

– “semi-private” methods for like objects – Double-dispatch when argument form matters.

slide-2
SLIDE 2

The Number Hierarchy

Object Magnitude Number Fraction Float Integer

slide-3
SLIDE 3

Instance protocol for Magnitude

= aMagnitude equality (like Magnitudes) < aMagnitude comparison (ditto) > aMagnitude comparison (ditto) <= aMagnitude comparison (ditto) >= aMagnitude comparison (ditto) min: aMagnitude minimum (ditto) max: aMagnitude maximum (ditto) Subclasses: Date, Natural

  • Compare Date with Date, Natural w/Natural, . . .
slide-4
SLIDE 4

Implementation of Magnitude: Reuse

(class Magnitude ; abstract class [subclass-of Object] (method = (x) (self subclassResponsibility)) ; may not inherit = from Object (method < (x) (self subclassResponsibility)) (method > (y) (y < self)) (method <= (x) ((self > x) not)) (method >= (x) ((self < x) not)) (method min: (aMag) ((self < aMag) ifTrue:ifFalse: {self} {aMag})) (method max: (aMag) ((self > aMag) ifTrue:ifFalse: {self} {aMag})) )

slide-5
SLIDE 5

The Number Hierarchy, Reprise

Object Magnitude Number Fraction Float Integer

slide-6
SLIDE 6

Instance protocol for Number

negated reciprocal abs absolute value + aNumber addition

  • aNumber

subtraction * aNumber multiplication / aNumber division (may answer a Fraction!) isNegative sign check isNonnegative sign check isStrictlyPositive sign check coerce: aNumber class of receiver, value of argument asInteger conversion asFraction conversion asFloat conversion

slide-7
SLIDE 7

Object-oriented design

Given that class Number inherits from class Magnitude, which of these methods of class Number can be implemented in terms of others? negated * coerce: reciprocal / asInteger abs isNegative asFraction + isNonnegative asFloat

  • isStrictlyPositive
slide-8
SLIDE 8

Concrete Number Methods

(method - (y) (self + (y negated))) (method abs () ((self isNegative) ifTrue:ifFalse: {(self negated)} {self})) (method / (y) (self * (y reciprocal))) (method isNegative () (self < (self coerce: 0))) (method isNonnegative () (self >= (self coerce: 0))) (method isStrictlyPositive () (self > (self coerce: 0)))

slide-9
SLIDE 9

Abstract Number Methods

(class Number [subclass-of Magnitude] ; abstract class ;;;;;;; arithmetic (method + (aNumber) (self subclassResponsibility)) (method * (aNumber) (self subclassResponsibility)) (method negated () (self subclassResponsibility)) (method reciprocal () (self subclassResponsibility)) ;;;;;;; coercion (method asInteger () (self subclassResponsibility)) (method asFraction () (self subclassResponsibility)) (method asFloat () (self subclassResponsibility)) (method coerce: (aNumber) (self subclassResponsibility)) )

slide-10
SLIDE 10

Extended Number Hierarchy

Object Magnitude Natural Number Fraction Float Integer SmallInteger LargeInteger LargePositiveInteger LargeNegativeInteger

slide-11
SLIDE 11

Example class Fraction: Initialization

(class Fraction [subclass-of Number] [ivars num den] ;; invariants: lowest terms, minus sign on top ;; maintained by divReduce, signReduce (class-method num:den: (a b) ((self new) initNum:den: a b)) (method initNum:den: (a b) ; private (self setNum:den: a b) (self signReduce) (self divReduce)) (method setNum:den: (a b) (set num a) (set den b) self) ; private .. other methods of class Fraction ... )

slide-12
SLIDE 12

Information revealed to self

Instance variables num and den

  • Directly available
  • Always and only go with self

Object knows its own representation, invariants, private methods:

(method asFraction () self) (method print () (num print) (’/ print) (den print) self) (method reciprocal () (((Fraction new) setNum:den: den num) signReduce))

slide-13
SLIDE 13

Information revealed to others

How would you implement coerce:? (Value of argument, representation of receiver)

(method asFraction () self) (method print () (num print) (’/ print) (den print) self) (method reciprocal () (((Fraction new) setNum:den: den num) signReduce)) (method coerce: (aNumber) ...)

Saved: Number protocol includes asFraction!

slide-14
SLIDE 14

Information revealed to others

How would you implement coerce:?

  • Value of argument, rep of receiver
  • Challenge: Can’t access rep of argument!

(method asFraction () self) (method print () (num print) (’/ print) (den print) self) (method reciprocal () (((Fraction new) setNum:den: den num) signReduce)) (method coerce: (aNumber) (aNumber asFraction))

Saved: Number protocol includes asFraction!

slide-15
SLIDE 15

The Number Hierarchy, Reprise

How to implement comparisons on Fractions? Object Magnitude Number Fraction Float Integer

slide-16
SLIDE 16

Instance protocol for Magnitude, Reprise

How to implement comparisons on Fractions?

= aMagnitude equality (like Magnitudes) < aMagnitude comparison (ditto) > aMagnitude comparison (ditto) <= aMagnitude comparison (ditto) >= aMagnitude comparison (ditto) min: aMagnitude minimum (ditto) max: aMagnitude maximum (ditto) Subclasses: Date, Natural

  • Compare Date with Date, Natural w/Natural, . . .
slide-17
SLIDE 17

Implementing comparison for Fractions

Alas! Cannot see representation of argument How will you know “equal, less or greater”?

slide-18
SLIDE 18

Implementing comparison for Fractions

Alas! Cannot see representation of argument Protocol says “like with like”? Extend the protocol

(method num () num) ; extension, semi-private (method den () den) ; extension, semi-private (method = (fr) ((num = (fr num)) and: {(den = (fr den))})) (method < (fr) ((num * (fr den)) < ((fr num) * den)))

slide-19
SLIDE 19

Extended protocol: Multiply two fractions

How will you multiply two fractions?

slide-20
SLIDE 20

Extending the protocol to multiply fractions

How will you multiply two fractions?

(method * (aFraction) (((Fraction new) setNum:den: (num * (aFraction num)) (den * (aFraction den))) divReduce))

slide-21
SLIDE 21

Extending open systems

Number protocol: like multiplies with like Goal:

  • Large integers and small integers are both Integers
  • Messages =, <, +, * ought to mix freely

Constraint: Each object has its own algorithm.

  • Small: Use machine-primitive multiplication
  • Large: Multiply magnitudes; choose sign

Double dispatch to the rescue!

slide-22
SLIDE 22

Double dispatch: Algebraic laws

Laws of multiplication:

(:+ n) * (:- m) == :- (n * m) (:+ n) * (:+ m) == :+ (n * m) (:+ n) * small == (:+ n) * (small asLargeInteger)

But! Can’t distinguish forms of argument Solution: “Dispatch laws”

(:+ n) * (:- m) == ((:- m) timesLP: self) (:+ n) * (:+ m) == ((:+ m) timesLP: self) (:+ n) * small == (small timesLP: self)

Argument to timesLP:

  • Understands “large positive integer” protocol
slide-23
SLIDE 23

Double dispatch methods encode operation & protocol

Example messages:

  • timesLP: arg

arg answers the large-positive integer protocol receiver should multiply itself by arg

  • plusSP: arg

arg answers the small-integer protocol receiver should add itself to arg Message encodes

  • Operation to be performed
  • Protocol accepted by argument
slide-24
SLIDE 24

Double dispatch to implement addition

How do you act?

  • As small integer, you’re asked to add large positive integer

N to self (aka plusLP: N) Response: ((self asLargeInteger) + N)

  • As small integer, you’re asked to add small integer n to

self (aka plusSP: n) Response: (self + n)

  • As large positive integer, you’re asked to add large

positive integer N to self (aka plusLP: N) Response: (self + n)

  • As large positive integer, you’re asked to add small integer

n to self (aka plusSP: n) Response: (self * (n asLargeInteger))

slide-25
SLIDE 25

Your turn: Double dispatch to implement multiplication

How do you act?

  • As small integer, you’re asked to multiply large positive

integer N by self (aka timesLP: N) Response: ((self asLargeInteger) * N)

  • As small integer, you’re asked to multiply small integer n

by self (aka timesSP: n) Response: (self * n)

  • As large positive integer, you’re asked to multiply large

positive integer N by self (aka timesLP: N) Response: (self * n)

  • As large positive integer, you’re asked to multiply small

integer n by self (aka timesSP: n) Response: (self * (n asLargeInteger))

slide-26
SLIDE 26

Your turn: Understanding double dispatch

On what class does each method go?

  • A. (method + (aNumber)

(aNumber addSmallIntegerTo: self))

  • B. (method * (anInteger)

(anInteger multiplyByLargePositiveInteger: self))

slide-27
SLIDE 27

Review: Two kinds of knowledge

I can send message to you:

  • I know your protocol

I can inherit from you:

  • I know my subclass responsibilities
slide-28
SLIDE 28

Knowledge of protocol

Three levels:

  • I know only your public methods

Example: send select: to any collection

  • You are like me: share semi-private methods

Example: send * or + to Fraction

  • I must get to know you: double dispatch

Example: send * to + to any integer

slide-29
SLIDE 29

Extra: Dealing with overflow

New law for multiplication: (self * small) = ((primitive mulWithOverflow self small {((self asLargeInteger) * small)}) value)) Primitive is not a method

  • Answers good block or exception block
  • Answer is then sent value