Polymorfie. zDefinitie ypolymorfie = ‘veel vormen’ -> in termen van programmeren : = enkele...

Preview:

Citation preview

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.

Recommended