Polymorfie
Polymorfie
Definitie polymorfie = ‘veel vormen’
-> in termen van programmeren : = enkele naam( van een klasse of een methode) verschillende code kan representeren, die door het een of andere
automatische mechanisme wordt geselecteerd => één enkele naam kan veel vormen aannemen => veel verschillende gedragingen uitdrukken
Polymorfie
Definitie veel verschillende gedragingen ook in gewone taal :
vb. openen-> deur openen-> doos openen-> bankrekening openen
Elk object (uit de echte wereld) interpreteert ‘openen’ op eigen manier, maar de actie blijft iets ‘openen’.
polymorfische taal = taal die polymorfie ondersteunt
Polymorfie
Definitie monomorfische taal = taal die geen polymorfie
ondersteunt = taal die alles en iedereen beperkt tot een enkel statisch gedrag, omdat elke naam statisch aan de bijbehorende code is gekoppeld
PolymorfieDefinitie Overerving -> mechanismen voor bepaalde
soorten polymorfie -> voor vervanging geschikte relaties
te vormen = geschiktheid voor inpluggen (pluggability)
belangrijk voor polymorfie: maakt
het mogelijk een specifiek type object op een algemene manier te behandelen
Polymorfie
Definitie voorbeeld: overervingshiërarchie van
PersonalityObject.
Polymorfie
Definitie speak( ) : in PersonalityObject en in alle
subklassen(=> vervangen methode; eigen definitie voor elke subklasse)
noarg constructors
Polymorfie
Definitie
Polymorfie
Definitie
Polymorfie
Definitie
Polymorfie
Definitie
Polymorfie
Definitie
Polymorfie
Definitie
array van PersonalityObject -> elk PersonalityObject vertoont een ander gedrag voor speak( ) => naam PersonalityObject lijkt verschillende gedragingen te vertonen voor speak( )
personalities = polymorfische variabele
Polymorfie
Definitie voorbeeld illustreert mechanisme van
polymorfie idee achter polymorfie -> methode
makeSpeak( )-> methode die
PersonalityObject als argument aanneemt
Polymorfie
Definitie Wegens overerving ->voor vervanging geschikte
relaties => argument van makeSpeak( ) = een instantie van PersonalityObject, of een willekeurige afstammeling daarvan
gespecialiseerde afstammelingen van Personality-Object kunnen gemaakt worden zoals Extro-vertedObject, zonder de methode makeSpeak( ) te veranderen om deze als argument aan te nemen.
Polymorfie
Definitie Polymorfie : wanneer makeSpeak( )
methodeaanroepen uitvoert naar argument -object
juiste methode van het PersonalityObject-
argument wordt aangeroepen gebaseerd op het echte type van de klasse van het argument, in plaats van op het type van de klasse die de methode makeSpeak( ) denkt te gebruiken
Polymorfie
Definitie
als argument van makeSpeak( ) = een ExtrovertedObject
wordt definitie van speak( ) van ExtrovertedObject
aangeroepen en niet de definitie van het PersonalityObject, de basisklasse die als argument aan makeSpeak( ) werd doorgegeven => verschillende meldingen op het scherm afhankelijk van het type van het argument
Polymorfie
Definitie nieuwe functionaliteit toevoegen aan systeem
-> op elk moment-> door nieuwe klassen te laten overerven
van de basisklasse met nieuwe functionaliteit
-> zonder bestaande code te wijzigen
toekomstbestendige software
Polymorfie
Definitie 4 soorten polymorfie:
-> inkapselende polymorfie-> parametrische polymorfie
-> overriding -> overloading
Inkapselende polymorfie
= inclusion polymorphism of 'pure polymorfie’
hierdoor mogelijk gerelateerde objecten op een algemene manier te behandelen
zie begin van dit hoofdstukmethode makeSpeak( )
Inkapselende polymorfie
Inkapselende polymorfie
Analoog voor IntrovertedObject en ExtrovertedObject
PessimisticObject, OptimisticObject, Introver-tedObject en ExtrovertedObject ‘zijn’ allemaal PersonalityObjecten
door vervangbaarheid en inkapselende
polymorfie -> maar één enkele methode voor
alle soorten PersonalityObjecten
Inkapselende polymorfie
Voordelen van inkapselende polymorfie: door vervangbaarheid : willekeurig Personality-
Object aan methode doorgeven
Polymorfie -> methode aanroepen op basis van het echte type van de instantie (OptimisticObject, IntrovertedObject, ExtrovertedObject of PessimisticObject), in plaats van op het schijnbare type (PersonalityObject)
Inkapselende polymorfie
Voordelen van inkapselende polymorfie: minder code schrijven:
->1 methode voor alle typen dan voor elk concreet type een afzonderlijke methode
->makeSpeak( ) kan met elk object werken waarvoor geldt: het object
‘is een’ PersonalityObject. makkelijker nieuwe subtypen toevoegen:
->geen specifieke methode nodig voor elk nieuw type => hergebruik van makeSpeak( )
Inkapselende polymorfie
Voordelen van inkapselende polymorfie: instanties van PersonalityObject lijken veel
verschillende gedragingen vertonen:=> makeSpeak( ): verschillende melding afhankelijk van de invoer van de methode => gedrag van systeem wijzigen door nieuwe klassen te introduceren door gebruik te maken van inkapselende polymorfie=> nieuwe gedrag zonder bestaande code te moeten wijzigen.
Inkapselende polymorfie
Voordelen van inkapselende polymorfie: vermijden van vele controles adhv verschillende
selectiestructuren=> voornaamste doel van overerving is
polymorfisch gedrag mogelijk te maken via voor vervanging geschikte relaties=> hergebruik zal automatisch optreden als op de juiste manier voor vervanging geschikte relaties gedefinieerd worden
Parametrische polymorfie
->algemene methoden en algemene typen =>iets eenmaal coderen, dat met veel verschillende soorten argumenten zal werken
Parametrische methoden = algemene methoden: door het declareren van
parametertypen uit te stellen tot het programma wordt uitgevoerd
bijvoorbeeld: som van twee gehele getallen kan voorgesteld worden door volgende methode:
Parametrische polymorfie
Parametrische methodenadd(a : geheel getal, b: geheel getal ) : geheel getal
=> argumenten: 2 gehele getallen=> niet mogelijk 2 reële getallen of 2 matrices als argument
add_matrix(a : matrix, b : matrix) : matrixadd_real(a : reëel getal, b: reëel getal ) : reëel getal
voor elk type een eigen add-methode
Parametrische polymorfie
Parametrische methodenbeter 1 methode dan veel methoden=> meer code=>meer kans op fouten=> moeilijker te onderhoudenbovendien geen natuurlijk model voor add( ):denken in termen van add( ) en niet
add_matrix( )en add_real( ).
Parametrische polymorfie
Parametrische methoden oplossing met inkapselende polymorfie:
klasse Addable met methode die weet hoe bij een object van deze klasse een andere instantie van addable moet opgeteld worden
Parametrische polymorfie
Parametrische methodennieuwe methode:add_addable(a : Addable, b: Addable) :
Addable
Parametrische polymorfie
Parametrische methoden= functiepolymorfie (of function polymorphism)
=> één methode voor optellen:-> maar de methode werkt alleen voor argumenten van het type Addable-> de Addables die aan de methode worden doorgegeven moeten van hetzelfde type zijn
=> methode = foutgevoelig en komt niet overeen met wat er door de interface wordt geïmpliceerd
Parametrische polymorfie
Parametrische methoden
originele probleem niet opgelostnog methode schrijven voor elk type dat geen Addable is
parametrische polymorfie: één methode voor het optellen van alle typen door uitstellen van het declareren van de typen van de argumenten
Parametrische polymorfie
Parametrische methodenadd(a : [T], b : [T]) : [T][T] beschouwen als een argument zoals a en bHet argument [T] specificeert het type voor a en b.=> uitstellen van definitie van het type van deargumenten tot het programma wordt uitgevoerd=> a en b hebben hetzelfde type [T]
Parametrische polymorfie
Parametrische methoden
Parametrische polymorfie
Parametrische methoden => argumenten moeten nog een specifieke
structuur hebben = een bepaalde methode of een op de juiste manier gedefinieerde operator moet zijn -> hier :elk element moet de bewerking + voor dat type definiëren
Parametrische polymorfie
Parametrische typen beschouw het ADT van een wachtrij:Queue [T]enqueue([T]) : void // elementen op de wachtrij plaatsendequeue( ) : [T] // elementen van de wachtrij afhalenisEmpty( ) : boolean // controle toestand van de wachtrijpeek( ) : [T] // voorste element bekijken zonder het te
verwijderen
=> geen wachtrijklasse voor elk type dat u in de wachtrij wilt kunnen opnemen, maar dynamisch tijdens het uitvoeren van het programma opgeven welk type elementen men wenst => De Queue is een Queue van een willekeurig type.
Parametrische polymorfie
Parametrische typen=>om Employees op te slaan: gebruik volgende declaratie :Gegevens: employee_queue : Queue[Employee]
In de main( ): employee_queue = nieuw Queue[Employee]
=> nu alleen instanties van Employee in de wachtrij opnemen met enqueue( ) of daar uit ophalen met dequeue( )
Parametrische polymorfie
Parametrische typenDoor gebruik van van parameters voorziene typen => maar eenmaal het ADT (wachtrij) schrijven en het dan gebruiken voor het opslaan van alle mogelijke typen
Geen ondersteuning voor van parameters voorziene typen of voor parametrische polymorfie in Java -> er bestaan Java-uitbreidingen voor het ondersteunen van parametrische polymorfie, maar deze zijn niet officieel door Sun goedgekeurd.
Overriding
= manier voor het vervangen van methoden
= belangrijk soort polymorfie vb: speak( ) werd vervangen in elke
subklasse van PersonalityObject vb: de klassen MoodyObject en
HappyObject
Overriding
Overriding
Overriding
Overriding
HappyObject vervangt getMood( ) maar niet queryMood( ) dat intern getMood( ) aanroept.=> queryMood( ) = recursieve methode Wordt queryMood( ) van een HappyObject aangeroepen, dan zorgt de instantiepolymorfie ervoor dat de vervangen versie van getMood( ) van HappyObject achter de coulissen wordt aangeroepen.=> geen herdefinitie van queryMood( ) nodig om de juist versie van getMood( ) aan te roepen
Overriding
=> gebruik van abstracte klassen
Overriding
abstracte methoden = uitgestelde methoden (of deferred methods)
-> definitie van de methode wordt overgelaten aan de afgestamde klassen-> abstracte methode kan op dezelfde manier aangeroepen worden als elke andere methode -> Polymorfie zorgt ervoor dat subklassen de juiste versie van de uitgestelde methode aanroepen
Overloading
= ad hoc polymorfie zelfde methodenaam voor verschillende methoden
verschil in• aantal parameters • en type van de parameters
vb: methode max( )+ max(a : geheel getal, b : geheel getal) : geheel getal + max(a : long, b: long ) : long+ max(a : float, b : float) : float+ max(a : double, b : double) : double
Overloading
Overloading is nuttig als een methode onafhankelijk is van zijn argumenten.
methode -> belangrijker dan zijn specifiekeparameters -> van toepassing op veel verschillende
soorten parametersbijv. max( ) -> neemt twee parameters aan en
vertelt welke van de twee het grootst is.
-> definitie is zelfde voor integers , floats, doubles
De bewerking + is een ander voorbeeld van een via overloading vervangen methode. Het idee + is onafhankelijk van zijn argumenten. U kunt allerlei soorten elementen optellen.
Overloading
ander voorbeeld: de bewerking + -> idee + is onafhankelijk van zijn
argumenten: allerlei soorten elementen kunnen opgeteld worden
in geval van geen overloading -> aparte methode, met unieke naam, voor elk type van argument => max( ): * geen abstract idee
* moet gedefinieerd worden in termen van de argumenten* niet meer natuurlijk gemodelleerd
Overloading
+ max_int(a : geheel getal, b : geheel getal) : geheel getal + max_long(a : long, b: long ) : long+ max_float(a : float, b : float) : float+ max_double(a : double, b : double) : double+ max_bird(a : bird, b : bird) : bird
=> geen polymorfisch gedrag -> enkel als dezelfde naam voor verschillende typen kan gebruikt worden; achter coulissen wordt de juiste methode aangeroepen voor het type van argument
Overloading
Dwang = coercion methode lijkt polymorfisch : argument van het
ene type wordt achter de coulissen in het verwachte type omgezet
bijv.:+ add(a : float, b : float) : float
-> twee float-argumenten worden bij elkaar opgeteld
OverloadingDwang
Maak gebruik van 2 integer variabelen(iA en iB) en roep add( ) aan:
iA = 1iB = 2add( iA, iB)
add( ) -> twee float-argumenten -> de compiler zet de int-argumenten in
floats om bij aanroep van add( ) -> voordat ze aan add( ) worden doorgegeven=> conversie (= cast in Java)
Overloading
Dwang=>add( ) lijkt polymorfisch (door dwang):
-> werkt met floats en met ints
Alternatief: add( ) vervangen via overloading:+ add(a : int, b : int) : int
=> add ( iA, iB ) niet door dwang maar juiste methode wordt via overloading
aangeroepen
Effectieve polymorfie
Wordt gegarandeerd door een paar stappen:wordt bereikt door effectieve inkapseling en
overerving zonder inkapseling kan code afhankelijk worden van
implementatie van klassen => er kan geen subklasse meer ingeplugd worden die deze
implementatie herdefinieert opm: publieke interface van een klasse of object
– = beschrijving van welke berichten naar die klasse of dat object kunnen gestuurd worden
– verschilt van de Java-interfaces:
Effectieve polymorfie
– verschilt van de Java-interfaces: definieert ook welke berichten naar de klasse kunnen gestuurd worden maar in de klasse kunnen nog extra publieke functies gedefinieerd worden
Java-interface publieke interface van klasse of object
– gebruik Java-interfaces om definitie van de interface te scheiden van de
klassenimplementatie – daardoor kunnen eventueel niet aan elkaar gerelateerde klassen dezelfde
interface implementeren– => objecten met een gemeenschappelijke interface kunnen, net als bij
overerving, ook deelnemen in voor vervanging geschikte relaties, zonder deel te hoeven uitmaken van dezelfde overervingshiërarchie.
Effectieve polymorfie
Overerving = belangrijk voor inkapselende polymorfie wegens de voor vervanging geschikte relatie kan worden aangemoedigd door goed uitgedachte
hiërarchieën:-> Verplaats gemeenschappelijke code naar abstracte klassen -> schrijf objecten die de abstracte klasse
gebruiken ipv van een specifieke, concrete afstammeling daarvan=> elke willekeurige afstammeling kan in programma opgenomen worden
Effectieve polymorfie
Tips: Volg de tips voor een effectieve inkapseling en
overerving. Programmeer op basis van interface, niet op basis van
de implementatie =>daardoor definieert men welke typen objecten aan het programma mogen deelnemen. De polymorfie zorgt ervoor dat deze objecten op de juiste manier deelnemen.
Denk en programmeer algemeen. -> details overlaten aan de polymorfie=>minder code
Effectieve polymorfieTips:
fundering voor de polymorfie leggen door voor vervanging geschikte relaties op te zetten en te gebruiken=>nieuwe subtypen kunnen toegevoegd worden=>juiste code wordt uitgevoerd bij gebruik van die subtypen
Als interface en de implementatie geheel van elkaar gescheiden kunnen worden =>voorkeur aan dat mechanisme boven overerving
bijv: Java-interface :mogelijk interface zonder implementatie te definiëren en te erven => meer flexibele vervangbaarheid en daardoor meer mogelijkheden voor het gebruiken van polymorfie.
Effectieve polymorfie
Tips:Gebruik abstracte klassen voor het scheiden van
de interface van de implementatie. Alle klassen die geen eindklassen zijn “moeten” abstract zijn - programmeer alleen op basis van deze abstracte klassen.