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
Polymorfie Definitie 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
toekomstbestendige software 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 hoofdstuk methode 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 methoden add(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) : matrix add_real(a : reëel getal, b: reëel getal ) : reëel getal voor elk type een eigen add-methode
Parametrische polymorfie Parametrische methoden beter 1 methode dan veel methoden => meer code=>meer kans op fouten => moeilijker te onderhouden bovendien 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 methoden nieuwe 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 opgelost nog 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 methoden add(a : [T], b : [T]) : [T] [T] beschouwen als een argument zoals a en b Het argument [T] specificeert het type voor a en b. => uitstellen van definitie van het type van de argumenten 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 plaatsen dequeue( ) : [T] // elementen van de wachtrij afhalen isEmpty( ) : boolean // controle toestand van de wachtrij peek( ) : [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 typen Door 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 verschil in vb: methode max( ) 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 specifieke parameters -> van toepassing op veel verschillende soorten parameters bijv. 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
Overloading Dwang Maak gebruik van 2 integer variabelen(iA en iB) en roep add( ) aan: iA = 1 iB = 2 add( 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 polymorfie Tips: 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.