html5-img
1 / 53

Polymorphism

Polymorphism. Poly => many Morph => shape Variables take on many shapes, or many classes of objects. 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. Object Model for Payroll.

primo
Download Presentation

Polymorphism

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  3. Object Model for Payroll abstract class * EmployeeTransaction * PayrollSystem Employee date postTo: abstract method post: Paycheck SalaryChange salary pay, taxes Timecard hoursWorked vacation Object-oriented Programming and Design

  4. Examples post: aTransaction aTransaction postTo: self. transactations add: aTransaction numbers inject: 0 into: [:sum :i | sum + i] 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 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] 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] 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. 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 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. Object-oriented Programming and Design

  11. Don’t Test Classes UndefinedObject Object isNil isNil ^ true ^ false notNil notNil ^ false ^ true Don’t test classes: use message sending and inheritance. Object-oriented Programming and Design

  12. Choices bad x class = UndefinedObject ifTrue: [...] x = nil ifTrue: [...] x isNil ifTrue: [...] x ifNil: […] best Object-oriented Programming and Design

  13. x ifNil: [ … ] Object ifNil: aBlock ^self UndefinedObject ifNil: aBlock ^aBlock value Object-oriented Programming and Design

  14. Magnitude Magnitude () Number () .... Character () Date ('day' 'year') Time ('hours' 'minutes' 'seconds') Object-oriented Programming and Design

  15. Number Hierarchy Number Fraction ('numerator' 'denominator') Integer () LargeNegativeInteger () LargePositiveInteger () SmallInteger () ... 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 => 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) 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] 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" 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 Object-oriented Programming and Design

  21. Refactoring raisedTo: raisedTo: power "Answer the receiver raised to a power." self = 1 ifTrue: [^ self]. ^ power timesMultiply: self 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 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 Object-oriented Programming and Design

  24. Double-dispatching: the Problem Fl Fr Fi M * Fl Fr Fi Sc Smallinteger Fl * Fl Fl Sc Float Fr Fl * Fi Sc Fraction Fi Fl Fi Sc * FixedPoint Sc Sc Sc Sc Matrix *

  25. Arithmetic Number * Matrix Multiply each element by number Matrix * Number Multiply each element by number Matrix * Matrix Standard matrix multiplication

  26. Arithmetic Integer * Integer Primitive int operations Integer * Float Convert int to float Float * Integer Convert int to float Float * Float Primitive float operation

  27. Double dispatching: the Solution • Primary method (+, *, etc) sends a second message to argument, encoding the class of the receiver. • 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 <primitive: 1> ^ anArg sumFromInteger: self 8.9 sumFromInteger: 37

  31. The second message dispatch 8.9 addSmallInteger: 37 FloataddSmallIngeter: anArg ^ anArg asFloat + self 8.9 + 37.0

  32. Finishing Up 8.9 + 37.0 Float+ anArg <primitive: 41> ^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" <primitive: 49> ^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. 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. … 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. Object-oriented Programming and Design

  44. Problem • Two user interface frameworks, Morphic and MVC • Application knows its UI frameworks • Refactor so app doesn’t know its UI 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 Object-oriented Programming and Design

  46. MorphicUIManager openMessageEditString: aString for: aBrowser ^aBrowser openAsMorphMessageEditing: aString 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. 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 Object-oriented Programming and Design

  49. Problem UIManager subclasses will accumulate application-specific code. Methods related to application should be in application package. Object-oriented Programming and Design

  50. Uses of Polymorphism Methods often depend radically on class of receiver. isNil ifTrue:ifFalse: double dispatching Object-oriented Programming and Design

More Related