Presentation is loading. Please wait.

Presentation is loading. Please wait.

Object-oriented Programming and Design 1 Polymorphism Poly => many Morph => shape Variables take on many shapes, or many classes of objects.

Similar presentations


Presentation on theme: "Object-oriented Programming and Design 1 Polymorphism Poly => many Morph => shape Variables take on many shapes, or many classes of objects."— Presentation transcript:

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 …


Download ppt "Object-oriented Programming and Design 1 Polymorphism Poly => many Morph => shape Variables take on many shapes, or many classes of objects."

Similar presentations


Ads by Google