Download presentation
Presentation is loading. Please wait.
Published bySabina Bradley Modified over 9 years ago
1
Object-oriented Programming and Design 1 Polymorphism Poly => many Morph => shape Variables take on many shapes, or many classes of objects.
2
Object-oriented Programming and Design 2 Polymorphism Polymorphism in OOP is caused by late- binding of procedure calls (message lookup). Program can work with any object that has the right set of methods.
3
Object-oriented Programming and Design 3 Object Model for Payroll Employee EmployeeTransaction PayrollSystem post: date Paycheck Timecard SalaryChange salary pay, taxes hoursWorked vacation : postTo: abstract class abstract method * *
4
Object-oriented Programming and Design 4 Examples post: aTransaction aTransaction postTo: self. transactations add: aTransaction numbers inject: 0 into: [:sum :i | sum + i]
5
Object-oriented Programming and Design 5 Many classes with same interface Examples Collections Numbers Magnitude Easier to remember method names Polymorphic clients can use any class
6
Object-oriented Programming and Design 6 Polymorphic client tasks := OrderedCollection new. tasks add: Task new. [tasks isEmpty] whileFalse: [ task := tasks removeLast. tasks addAll: task computeNewTasks]
7
Object-oriented Programming and Design 7 Polymorphic client tasks := SortedCollection sortBlock: [:first :second | first priority > second priority]. tasks add: Task new. [tasks isEmpty] whileFalse: [ task := tasks removeLast. tasks addAll: task computeNewTasks]
8
Object-oriented Programming and Design 8 Polymorphism instead of Case Statements Smalltalk has no case statement. OO programmers tend to replace case statements with message sending. Instead of making a new case, add a subclass.
9
Object-oriented Programming and Design 9 Eliminating Cases exp case: 1 do: [...]; case: 15 do: [...]. Make classes for 1 and 15, with a method called msg. exp msg or (dictionary at: exp) msg
10
Object-oriented Programming and Design 10 Class UndefinedObject Class UndefinedObject has one instance -- nil. All variables are initialized to nil. Also used to indicate illegal value.
11
Object-oriented Programming and Design 11 Don’t Test Classes UndefinedObjectObject isNil ^ true^ false notNil ^ false^ true Don’t test classes: use message sending and inheritance.
12
Object-oriented Programming and Design 12 Choices bad x class = UndefinedObject ifTrue: [...] x = nil ifTrue: [...] x isNil ifTrue: [...] x ifNil: […] best
13
Object-oriented Programming and Design 13 x ifNil: [ … ] Object ifNil: aBlock ^self UndefinedObject ifNil: aBlock ^aBlock value
14
Object-oriented Programming and Design 14 Magnitude Magnitude () Number ().... Character () Date ('day' 'year') Time ('hours' 'minutes' 'seconds')
15
Object-oriented Programming and Design 15 Number Hierarchy Number Fraction ('numerator' 'denominator') Integer () LargeNegativeInteger () LargePositiveInteger () SmallInteger ()...
16
Object-oriented Programming and Design 16 Numbers Numbers are part of the class hierarchy, not built into compiler. Numbers understand +, -, *, /, <, <=, etc. 3 / 6 => 1 / 2 2 sqrt => 1.41421 3 + 4 * 2 =>
17
Object-oriented Programming and Design 17 Numbers are polymorphic (3/4) * 0.45 + 4.6s2 4.9375 (0.45 + 4.6s2) / 17 0.297059 (0.45 + 4.6s2) truncated / 17 (5/17)
18
Object-oriented Programming and Design 18 Polymorphism, not conditionals Don’t explicitly check class of argument. Use polymorphism to make computation depend on class of argument. aThing class = A ifTrue: [self doStuffWith: aThing] ifFalse: [self doSomethingElseWith: aThing]
19
Object-oriented Programming and Design 19 Original in Number raisedTo: aNumber "Answer the receiver raised to aNumber." aNumber isInteger ifTrue: ["Do the special case of integer power" ^ self raisedToInteger: aNumber]. self < 0 ifTrue: [ self error: self printString, ' raised to a non-integer power' ]. aNumber = 0 ifTrue: [^ 1]."Special case of exponent=0" (self = 0) | (aNumber = 1) ifTrue: [^ self]."Special case of exponent=1" ^ (aNumber * self ln) exp"Otherwise use logarithms"
20
Object-oriented Programming and Design 20 Original in Number raisedToInteger: operand "Answer the receiver raised to the power operand, an Integer." | count result | operand = 0 ifTrue: [^ self class one]. operand = 1 ifTrue: [^ self]. operand < 0 ifTrue: [^ (self raisedToInteger: operand negated) reciprocal]. count := 1. [(count := count + count) < operand] whileTrue. result := self class one. [count > 0] whileTrue: [result := result * result. (operand bitAnd: count) = 0 ifFalse: [result := result * self]. count := count bitShift: -1]. ^ result
21
Object-oriented Programming and Design 21 Refactoring raisedTo: raisedTo: power "Answer the receiver raised to a power." self = 1 ifTrue: [^ self]. ^ power timesMultiply: self
22
Object-oriented Programming and Design 22 Integer timesMultiply: aNumber | count result | self = 0 ifTrue: [^ aNumber class one]. self < 0 ifTrue: [^ (self negated timesMultiply: aNumber) reciprocal]. count := 1. [(count := count + count) < self] whileTrue. result := 1. [count > 0] whileTrue: [result := result * result. (self bitAnd: count) = 0 ifFalse: [result := result * aNumber]. count := count bitShift: -1]. ^ result
23
Object-oriented Programming and Design 23 Number timesMultiply: aNumber | truncated | aNumber < 0.0 ifTrue: [(truncated := self truncated) = self ifTrue: ["self is a whole number." ^ (truncated timesMultiply: aNumber) * self class one]. ArithmeticError signal: aNumber printString, ' : negative number raised to a non-integer power']. ^ (self * aNumber ln) exp
24
Double-dispatching: the Problem Float Smallinteger Fraction FixedPoint Matrix Fr Sc Fi FlM * * * * * Fl Fl Fl FlFl Fr Fr Fl Fi Fi Sc Sc Sc Sc Sc Sc Sc Fi Fi
25
Arithmetic Number * Matrix Multiply each element by number Matrix * Number Multiply each element by number Matrix * Matrix Standard matrix multiplication
26
Arithmetic Integer * IntegerPrimitive int operations Integer * FloatConvert int to float Float * IntegerConvert int to float Float * FloatPrimitive float operation
27
Double dispatching: the Solution l Primary method (+, *, etc) sends a second message to argument, encoding the class of the receiver. l Second message knows class of both its argument and its receiver.
28
Primary operations Send a second message, encoding the class of the original receiver in the name of the message. + anArg anArg sumFromInteger: self
29
Double Dispatching Methods Knows the class of receiver and argument. sumFromInteger: anInteger ^anInteger asFloat + self
30
The first message dispatch 37 + 8.9 SmallInteger + anArg ^ anArg sumFromInteger: self 8.9 sumFromInteger: 37
31
The second message dispatch 8.9 addSmallInteger: 37 Float addSmallIngeter: anArg ^ anArg asFloat + self 8.9 + 37.0
32
Finishing Up 8.9 + 37.0 Float + anArg ^aNumber sumFromFloat: self
33
Multiplication Fraction has two instance variables, numerator and denominator. * aNumber "Result is a new Fraction unless the argument is a Float, in which case the result is a Float." ^aNumber productFromFraction: self
34
Fraction productFromFraction: aFraction ^(self species numerator: aFraction numerator * numerator denominator: aFraction denominator * denominator) reduced
35
Integer productFromFraction: aFraction ^(aFraction species numerator: aFraction numerator * self denominator: aFraction denominator) reduced
36
Float productFromFraction: aFraction ^aFraction asFloat * self
37
Float * aNumber "Answer a Float that is the result of multiplying the receiver by the argument, aNumber. The primitive fails if it cannot coerce the argument to a Float" ^aNumber productFromFloat: self
38
Fraction productFromFloat: aFloat ^aFloat * self asFloat
39
Shared Responsibilities Sometimes need to select a method based on class of several objects: Displaying object -- depends on both the kind of object and the windowing system Arithmetic -- depends on the types of both arguments
40
Double dispatching Three kinds of mesages primary operations double dispatching methods forwarding operations Implement inheriting from superclass of argument Implement commutativity
41
Cost of Double Dispatching Adding a new class requires adding a message to each of the other classes. Worst case is N*N methods for N classes. However, total lines of code is not much larger.
42
Object-oriented Programming and Design 42 openMessageEditString: aString "Create a pluggable version of the views for a Browser that just shows one message." | messageListView browserCodeView topView annotationPane underPane y | Smalltalk isMorphic ifTrue: [^ self openAsMorphMessageEditing: aString]. topView := (StandardSystemView new) model: self. topView borderWidth: 1. "label and minSize taken care of by caller" messageListView := PluggableListView on: self list: #messageListSingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #messageListMenu:shifted:. messageListView window: (0 @ 0 extent: 200 @ 12). topView addSubView: messageListView. …
43
Object-oriented Programming and Design 43 openOnClassWithEditString: aString "Create a pluggable version of all the views for a Browser, including views and controllers." | classListView messageCategoryListView messageListView browserCodeView topView switchView annotationPane underPane y optionalButtonsView | Smalltalk isMorphic ifTrue: [^ self openAsMorphClassEditing: aString]. topView := (StandardSystemView new) model: self. topView borderWidth: 1. "label and minSize taken care of by caller" classListView := PluggableListView on: self list: #classListSingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #classListMenu:shifted: keystroke: #classListKey:from:. classListView window: (0 @ 0 extent: 100 @ 12). topView addSubView: classListView.
44
Object-oriented Programming and Design 44 Problem l Two user interface frameworks, Morphic and MVC l Application knows its UI frameworks l Refactor so app doesn’t know its UI
45
Object-oriented Programming and Design 45 Solution Have method delegate to an object that might be either a Morphic expert or a MVC expert openMessageEditString: aString ^UIManager default openMessageEditString: aString for: self
46
Object-oriented Programming and Design 46 MorphicUIManager openMessageEditString: aString for: aBrowser ^aBrowser openAsMorphMessageEditing: aString
47
Object-oriented Programming and Design 47 MVCUIManager openMessageEditString: aString for: aBrowser | topView messageListView … | topView := (StandardSystemView new) model: aBrowser. topView borderWidth: 1. "label and minSize taken care of by caller" messageListView := PluggableListView on: aBrowser list: #messageListSingleton selected: #indexIsOne changeSelected: #indexIsOne: menu: #messageListMenu:shifted:. messageListView window: (0 @ 0 extent: 200 @ 12). topView addSubView: messageListView.
48
Object-oriented Programming and Design 48 First attempt To get rid of isMorphic Change method to delegate to UIManager default Copy old method into MVCUIManager and MorphicUIManager Replace “isMorphic” with “true” or “false” Simplify
49
Object-oriented Programming and Design 49 Problem UIManager subclasses will accumulate application-specific code. Methods related to application should be in application package.
50
Object-oriented Programming and Design 50 Uses of Polymorphism Methods often depend radically on class of receiver. isNil ifTrue:ifFalse: double dispatching
51
Object-oriented Programming and Design 51 Double dispatch l Sometimes method needs to depend on class of receiver AND class of argument l Solution: l First method sends message to argument, encoding type of original receiver in the message name l Second method knows type of both receiver and argument
52
Object-oriented Programming and Design 52 Double dispatch in browser Browser>>displayWith: aUIManager aUIManager displayBrowser: self MorphicUIManager>>displayBrowser: aBrowser …
53
Object-oriented Programming and Design 53 Polymorphism More significant than inheritance. Requires standard interfaces. Many different uses: Template methods standard interfaces eliminating conditionals …
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.