10.5 Polymorphism • QuestionDemo2passedtwoChoiceQuestionobjectstothepresentQuestion()method• CanwewriteapresentQuestion()methodthatdisplaysbothQuestionandChoiceQuestiontypes?
• Withinheritance,thisgoalisveryeasytorealize!• Inordertopresentaques9ontotheuser,weneednotknowtheexacttypeoftheques9on.
• Wejustdisplaytheques9onandcheckwhethertheusersuppliedthecorrectanswer.
defpresentQuestion(q):q.display()response=input("Youranswer:")print(q.checkAnswer(response))
11/11/16 39
Which Display() method was called? • presentQuestion()simplycallsthedisplay()methodofwhatevertypeispassed:
defpresentQuestion(q):q.display()...
! IfpassedanobjectoftheQuestionclass:" Questiondisplay()
! IfpassedanobjectoftheChoiceQuestionclass:" ChoiceQuestiondisplay()
display()
__
11/11/16 40
• Thevariableqdoesnotknowthetypeofobjecttowhichitrefers:
Why Does This Work? • AsdiscussedinSec9on10.1,wecansubs9tuteasubclassobjectwheneverasuperclassobjectisexpected:
second=ChoiceQuestion()presentQuestion(second)#OKtopassaChoiceQuestion
11/11/16 41
• Notehoweveryoucannotsubs9tuteasuperclassobjectwhenasubclassobjectisexpected.• AnAttributeErrorexcep9onwillberaised.• Theparentclasshasfewercapabili9esthanthechildclass(youcannotinvokeamethodonanobjectthathasnotbeendefinedbythatobject’sclass).
Polymorphism Benefits • InPython,methodcallsarealwaysdeterminedbythetypeoftheactualobject,notthetypeofthevariablecontainingtheobjectreference• Thisiscalleddynamicmethodlookup• Dynamicmethodlookupallowsustotreatobjectsofdifferentclassesinauniformway
• Thisfeatureiscalledpolymorphism
• Weaskmul9pleobjectstocarryoutatask,andeachobjectdoessoinitsownway
• Polymorphismmakesprogramseasilyextensible
11/11/16 42
Questiondemo3.py (1)
Creates an object of the Question class
Creates an object of the ChoiceQuestion class, uses new addChoice() method.
Calls presentQuestion()- next page - passed both types of objects.
11/11/16 43
Questiondemo3.py (2)
Receives a parameter of the super-class type
Uses appropriate display method.
11/11/16 44
Special Topic 10.2
• willreturnTrueifqisaninstanceoftheQuestionclassorofany
subclassthatextendstheQuestionclass,• otherwise,itreturnsFalse.
isinstance(q,Question)
11/11/16 45
• SubclassesandInstances:• Youlearnedthattheisinstance()func9oncanbeusedtodetermineifanobjectisaninstanceofaspecificclass.
• Buttheisinstance()func9oncanalsobeusedtodetermineifanobjectisaninstanceofasubclass.
• Forexample,thefunc9oncall:
Use of Isinstance()! Acommonuseoftheisinstance()func9onistoverifythattheargumentspassedtoafunc9onormethodareofthecorrecttype.
defpresentQuestion(q):ifnotisintance(q,Question):raiseTypeError("TheargumentisnotaQuestionoroneofitssubclasses.")
11/11/16 46
Special Topic 10.3 • DynamicMethodLookup
• SupposewemovethepresentQuestion()methodtoinsidetheQuestionclassandcallitasfollows:
cq=ChoiceQuestion()cq.setText("InwhichcountrywastheinventorofPythonborn?")...cq.presentQuestion()
defpresentQuestion(self):self.display()response=input("Your answer: ")print(self.checkAnswer(response))
11/11/16 47
• Whichdisplay()andcheckAnswer()methodswillbecalled?
Dynamic Method Lookup • IfyoulookatthecodeofthepresentQuestion()method,youcanseethatthesemethodsareexecutedontheselfreferenceparameter.• Becauseofdynamicmethodlookup,theChoiceQuestionversionsofthedisplay()andcheckAnswer()methodsarecalledautoma9cally.
• ThishappenseventhoughthepresentQuestion()methodisdeclaredintheQuestionclass,whichhasnoknowledgeoftheChoiceQuestionclass.
classQuestion:defpresentQuestion(self):self.display()response=input("Youranswer:")print(self.checkAnswer(response))
11/11/16 48
Special Topic 10.4 • AbstractClassesandmethods
• Ifitisdesirabletoforcesubclassestooverrideamethodofabaseclass,youcandeclareamethodasabstract.• Youcannotinstan9ateanobjectthathasabstractmethods
• Thereforetheclassisconsideredabstract(ithas1+abstractmethods)
• It’satooltoforceprogrammerstocreatesubclasses(avoidsthetroubleofcomingupwithuselessdefaultmethodsthatothersmightinheritbyaccident).
• InPython,thereisnoexplicitwaytospecifythatamethodisanabstractmethod.Instead,thecommonprac9ceamongPythonprogrammersistohavethemethodraiseaNotImplementedErrorexcep9onasitsonlystatement:
classAccount:...defdeductFees(self):raiseNotImplementedError
11/11/16 49
Common Error 10.3 • Don’tUseTypeTests
• Someprogrammersusespecifictypetestsinordertoimplementbehaviorthatvarieswitheachclass:
ifisinstance(q,ChoiceQuestion):#Don’tdothis.#DothetasktheChoiceQuestionway.elifisinstance(q,Question):#DothetasktheQuestionway.
elifisinstance(q,NumericQuestion):#DothetasktheNumericQuestionway.
11/11/16 50
• Thisisapoorstrategy.• IfanewclasssuchasNumericQuestionisadded,thenyouneedtoreviseallpartsofyourprogramthatmakeatypetest,addinganothercase:
Alternate to Type Tests • Polymorphism
• Wheneveryoufindyourselftryingtousetypetestsinahierarchyofclasses,reconsiderandusepolymorphisminstead.
• DeclareamethoddoTheTask()inthesuperclass,overrideitinthesubclasses,andcall
q.doTheTask()
11/11/16 51
Steps to Using Inheritance • Asanexample,wewillconsiderabankthatofferscustomersthefollowingaccounttypes:1) A savings account that earns interest. The interest compounds monthly and is
based on the minimum monthly balance. 2) A checking account that has no interest, gives you three free withdrawals per
month, and charges a $1 transaction fee for each additional withdrawal. • Theprogramwillmanageasetofaccountsofbothtypes
• Itshouldbestructuredsothatotheraccounttypescanbeaddedwithoutaffec9ngthemainprocessingloop.
• Themenu:D)epositW)ithdrawM)onthendQ)uit• Fordepositsandwithdrawals,querytheaccountnumberandamount.Printthebalanceoftheaccounta`ereachtransac9on.
• Inthe“Monthend”command,accumulateinterestorclearthetransac9oncounter,dependingonthetypeofthebankaccount.Thenprintthebalanceofallaccounts.
11/11/16 52
Steps to Using Inheritance 1)Listtheclassesthatarepartofthehierarchy.SavingsAccountCheckingAccount2)Organizetheclassesintoaninheritance.hierarchyBaseonsuperclassBankAccount
11/11/16 53
3)Determinethecommonresponsibili9es.a.WritePseudocodeforeachtaskb.Findcommontasks
Using Inheritance: Pseudocode
11/11/16 54
Steps to Using Inheritance 4)Decidewhichmethodsareoverriddeninsubclasses.
• Foreachsubclassandeachofthecommonresponsibili9es,decidewhetherthebehaviorcanbeinheritedorwhetheritneedstobeoverridden
5)Declarethepublicinterfaceofeachsubclass.• Typically,subclasseshaveresponsibili9esotherthanthoseofthesuperclass.Listthose,aswellasthemethodsthatneedtobeoverridden.
• Youalsoneedtospecifyhowtheobjectsofthesubclassesshouldbeconstructed.
6)Iden9fyinstancevariables.• Listtheinstancevariablesforeachclass.Placeinstancevariablesthatarecommontoallclassesinthebaseofthehierarchy.
7)Implementconstructorsandmethods.8)Constructobjectsofdifferentsubclassesandprocessthem.
11/11/16 55
Eye Break
11/11/16 56
10.6 Application • Crea9ngageometricshapeclasshierarchy
• TocreatecomplexscenesbeyondthesimplegraphicsintroducedinChapter2,youmayneedalargenumberofshapesthatvaryincolor,size,orloca9on.
• Ratherthancallingthevariousmethodsagainandagain,itwouldbeusefultohaveclassesthatmodelthevariousgeometricshapes.
• Usingshapeclasses,aprogrammercancreateashapeobjectwithspecificcharacteris9cs,thenusethesameobjecttodrawmul9pleinstancesoftheshapewithonlyminorchanges.
11/11/16 57
Inheritance Diagram of Geometric Shapes
11/11/16 58
The Base Class • TheGeometricShapeclassshouldprovidethefunc9onalitythatiscommonamongthevarioussubclasses:• Sedngthecolorsusedtodrawtheshape.• Gedngandsedngthecoordinatesfortheupper-le`cornerofaboundingbox.
• Compu9ngthewidthandheightoftheshape(ortheboundingboxusedtodefinetheshape).
• Drawingtheshapeonacanvas.
• Duetotheamountofvaria9onbetweenshapesallsubclasseswillhavetooverridethedraw()method.
11/11/16 59
Attributes of the Base Class • Theinstancevariables_filland_outlinecanstorethefillandoutlinecolorsusedbytheshapes.
• Coordinatesofthetople`handcorneroftheboundingboxfortheshapecanbestoredintheinstancevariables_xand_y
11/11/16 60
Setting the Attributes • TheconstructoroftheGeometricShapebaseclassneedstodefinethecommoninstancevariables.
classGeometricShape:##Constructabasicgeometricshape.#@paramxthex-coordinateoftheshape#@paramythey-coordinateoftheshapedef__init__(self,x,y):self._x=xself._y=yself._fill=Noneself._outline="black"
11/11/16 61
Accessor Methods • Asexpectedtheywillreturnthevaluesstoredintheinstancevariables.
defgetX(self):returnself._xdefgetY(self):returnself._y
defgetWidth(self):return0defgetHeight(self):return0
11/11/16 62
• BecausethegetWidth()andgetHeight()methodsreturnzerotheyshouldbeoverriddenbysubclasses.
Mutator Methods • Wedefinethreemutatormethodsforsedngthecolors.
• Twomethodssettheoutlineorfillcolorindividually,andthethirdmethodsetsbothtothesamecolor:
defsetFill(self,color=None):self._fill=colordefsetOutline(self,color=None):self._outline=colordefsetColor(self,color):self._fill=colorself._outline=color
11/11/16 63
Other Methods • Themove()methodmovestheshapebyagivenamount(x,y)coordinates.
defmoveBy(self,dx,dy):self._x=self._x+dxself._y=self._y+dy
defdraw(self,canvas):canvas.setFill(self._fill)canvas.setOutline(self._outline)
11/11/16 64
• Asindicatedearlier,thedraw()methodhastobeoverriddenforeachsubclass’sspecificshapebutthecommonopera9on(sedngthedrawingcolors)isincludedhere.
The Rectangle Class (1) • TheRectangleclassinheritsfromGeometricShape.
• Theconstructorpassestheupper-le`cornertothesuperclassandstoresthewidthandheight.
def__init__(self,x,y,width,height):super().__init__(x,y)self._width=widthself._height=height
11/11/16 65
The Rectangle Class (2) • ThedrawmethodisoverriddenintheRectanglesubclasstoincludethecalltotheappropriatecanvasmethod.
• Accessorsareoverridden(fromtheonesthatreturnzero).
defdraw(self,canvas):super().draw(canvas)#Parentmethodsetscolorscanvas.drawRect(self.getX(),self.getY(),self._width,self._height)
defgetWidth(self):returnself._widthdefgetHeight(self):returnself._height
11/11/16 66
The Line Class (1) • Alineisspecifiedbyitsstartandendpoints.
11/11/16 67
• Itispossiblethatneitherofthesepointsistheupper-le`corneroftheboundingbox.
• Instead,weneedtocomputethesmallerofthex-andy-coordinatesandpassthosevaluestothesuperclassconstructor.
The Line Class (2) • Wealsoneedtostorethestartandendpointsininstancevariablesbecauseweneedthemtodrawtheline.
def__init__(self,x1,y1,x2,y2):super().__init__(min(x1,x2),min(y1,y2))self._startX=x1self._startY=y1self._endX=x2self._endY=y2
11/11/16 68
Line Class: Methods (1) • Thewidthandheightarethedifferencesbetweenthestar9ngandendingx-andy-coordinates.
• However,ifthelineisn’tslopingdownward,weneedtotaketheabsolutevaluesofthedifference.
defgetWidth(self):returnabs(self._endX-self._startX)defgetHeight(self):returnabs(self._endY-self._startY)
11/11/16 69
Line Class: Methods (2) • Asnotedthedraw()methodmustbeoverriddendefdraw(self,canvas):super().draw(canvas)canvas.drawLine(self._startX,self._startY,self._endX,self._endY)
defmoveBy(self,dx,dy):super().moveBy(dx,dy)self._startX=self._startX+dxself._startY=self._startY+dyself._endX=self._endX+dxself._endY=self._endY+dy
11/11/16 70
• AlsothemoveBy()methodmustbeoverriddensothatitadjuststhestar9ngandendingpoints,inaddi9ontothetop-le`corner.
Wrapper Class: Square• Awrapperclasswrapsorencapsulatesthefunc9onalityofanotherclasstoprovideamoreconvenientinterface.
• Forexample,wecoulddrawasquareusingtheRectanglesubclass.• Butitrequiresthatwesupplyboththewidthandheight.• Becauseasquareisaspecialcaseofarectangle,wecandefineaSquaresubclassthatextends,orwraps,theRectangleclassandonlyrequiresonevalue,thelengthofaside.
classSquare(Rectangle):def__init__(self,x,y,size):super().__init__(x,y,size,size)
11/11/16 71
Testshapes.py
11/11/16 72
Groups of Shapes • TheGroupsubclassdoesnotactuallydrawageometricshape.
• Insteaditcanbeusedtogroupbasicgeometricshapestocreateacomplexshape.• Forexample,supposeyouconstructadoorusingarectangle,acircleforthedoorknob,andacircleforthepeephole.
• ThethreecomponentscanbestoredinaGroupinwhichtheindividualshapesaredefinedrela9vetotheposi9onofthegroup.
• Thisallowstheen9regrouptobemovedtoadifferentposi9onwithouthavingtomoveeachindividualshape.
11/11/16 73
The Group Class • TocreateaGroup,youprovidethecoordinatesoftheupper-le`cornerofitsboundingbox.
• Theclassdefinesaninstancevariablethatstorestheshapesinalist.• AsnewshapesareaddedtoaGroupobject,thewidthandheightoftheboundingboxexpandstoenclosethenewshapes.
11/11/16 74
Group Class Methods (1) • Createthegroupwithitsboundingboxposi9onedat(x,y).
def__init__(self,x=0,y=0):super().__init__(x,y)self._shapeList=[]
defadd(self,shape):self._shapeList.append(shape)
11/11/16 75
• Addingashapetothegroupinvolvesseveralsteps.• First,theshapehastobeappendedtothelist:
Group Class Methods (2) • Theindividualshapesareposi9onedrela9vetotheupper-le`cornerofthegroup’sboundingbox.
• Wemustensurethateachshapeisposi9onedbelowandtotherightofthispoint.Ifitisnot,itmustbemoved.
#Keeptheshapewithintopandleftedgesofthe#boundingbox.ifshape.getX()<0:shape.moveBy(-shape.getX(),0)ifshape.getY()<0:shape.moveBy(0,-shape.getY())
11/11/16 76
Group Class Methods (3) • Thewidthofthegroupisdeterminedbytherightmostextentofanyofthegroup’smembers.
• Therightmostextentofashapeisshape.getX()+shape.getWidth().Thefollowingmethodcomputesthemaximumoftheseextents.
defgetWidth(self):width=0forshapeinself._shapeList:width=max(width,shape.getX()+shape.getWidth())returnwidth
11/11/16 77
Group Class Methods (4) • Theheightofthegroup(thebohommostextent)iscomputedinthesamewayasthewidth.
defgetHeight(self):height=0forshapeinself._shapeList:height=max(height,shape.getY()+shape.getHeight())returnheight
11/11/16 78
Group Class Methods (5) • Theen9regroupcanbedrawnonthecanvas.• Theshapescontainedinthegrouparedefinedrela9vetotheupper-le`cornerofitsboundingbox.
• Beforeashapecanbedrawn,ithastobemovedtoitsposi9onrela9vetotheupper-le`cornerofthegroup’sboundingbox.
defdraw(self,canvas):forshapeinself._shapeList:shape.moveBy(self.getX(),self.getY())shape.draw(canvas)shape.moveBy(-self.getX(),-self.getY())
11/11/16 79
Summary: Inheritance • Asubclassinheritsdataandbehaviorfromasuperclass.• Youcanalwaysuseasubclassobjectinplaceofasuperclassobject.• Asubclassinheritsallmethodsthatitdoesnotoverride.• Asubclasscanoverrideasuperclassmethodbyprovidinganewimplementa9on.
• InPythonaclassnameinsideparenthesesintheclassheaderindicatesthataclassinheritsfromasuperclass.
11/11/16 80
Summary: Overriding Methods
• Anoverridingmethodcanextendorreplacethefunc9onalityofthesuperclassmethod.
• Usethereservedwordsupertocallasuperclassmethod.• Tocallasuperclassconstructor,usethesuperreservedwordbeforethesubclassdefinesitsowninstancevariables.
• Theconstructorofasubclasscanpassargumentstoasuperclassconstructor,usingthereservedwordsuper.
11/11/16 81
Summary: Polymorphism • Asubclassreferencecanbeusedwhenasuperclassreferenceisexpected.• Polymorphism(“havingmul9pleshapes”)allowsustomanipulateobjectsthatshareasetoftasks,eventhoughthetasksareexecutedindifferentways.
• Anabstractmethodisamethodwhoseimplementa9onisnotspecified.
11/11/16 82
Summary: Use Inheritance for Designing a Hierarchy of Shapes
• TheGeometricShapeclassprovidesmethodsthatarecommontoallshapes.
• •EachsubclassofGeometricShapemustoverridethedraw()method.
• Ashapeclassconstructormustini9alizethecoordinatesofitsupper-le`corner.
• Eachshapesubclassmustoverridethemethodsforcompu9ngthewidthandheight.
• AGroupcontainsshapesthataredrawnandmovedtogether.
11/11/16 83