TDDD78 Objektorientering i Java, del 2 Objektvariabler är pekare vad är det? Hur används pekare för att sätta samman objekt (composition)? Hur används hierarkier för att modellera nära relaterade typer? jonas.kvarnstrom@liu.se 2017
Viktiga begrepp inte bara inom objektorientering
Motivation 3 Programmeringsuppgift: Lagra info om anställda Håll reda på varje anställds närmaste chef som också är en anställd! En första ansats:
Motivation (2): Innehåll? 4 Ser ut som att en innehåller en annan Jag Mitt namn Chefen Chefens namn
Motivation (3): Innehåll? 5 Kan bli problematiskt! Andra kan inte innehålla samma objekt! Jag Chefen Chefens chef Högsta chefen Hur får man stopp på det? Två platser i minnet olika objekt! Min kollega Samma chef!
Motivation (4): En bättre lösning 6 En anställd ska inte innehålla chefen, utan peka ut vem chefen är Jag Min kollega Chefen Chefens chef Högsta chefen Så: Hur pekar man på ett annat objekt?
Variabler och minnesadresser 7 Programkod Minne vid körning Använd minnesadresser! Finns alltid där "i bakgrunden": " " "lagra 32-bitars heltal 10 på adress 10000 10003" " "Skapa -objekt på adress 50000 50047" "
Variabler och minnesadresser (2) 8 Programkod Minne vid körning I vissa språk får man veta minnesadresserna C:
Pekare (1) 9 Programkod Minne vid körning En variabel av pekartyp kan innehålla en adress C: "pekare till " heter Värdet blir adressen Värdet 10004 är adressen till ett annat värde i minnet
Pekare (2): Tilldelning 10 Programkod Minne vid körning Ändra pekarens värde ändra vart den pekar C:
Objektvariabler är pekare 12 Java: En objektvariabel är alltid en pekare! Namn Värde i minnet 2. Skapa variabeln, låt den peka på obj. 1. Skapa objektet (minne, konstruktor, ) mycircle är egentligen pekaren (4/8 bytes), inte objektet! Java gömmer numeriska värdet (irrelevant för vår kod): Vi kan inte få fram talet 49152
Men vilka konsekvenser får detta?
Pekare i Java (1): Objektmedlemmar 14 Att komma åt medlemmar: T.ex. Beräknar ; går automatiskt vidare till objektet på plats 49152 Hittar fältet ; ändrar dess värde Namn Värde i minnet
Pekare i Java (2): Exempel 15 Namn Värde i minnet Anta två cirklar:
Pekare i Java (3): Tilldelning 16 Namn Värde i minnet är pekare Ändra pekarens värde ändra vart den pekar Sätter till 10000 Kommer inte att kopiera själva cirkeln, fält för fält! Kvarvarande objekt som ingen pekar på inte ett problem i Java (skräpsamling)
Pekare i Java (4): 17 Namn Värde i minnet Nu är också och är två variabler, pekar på samma objekt och är samma variabel! "Peter Dalenius" är en sträng "Kursens studierektor" är en annan Men de pekar ut samma person Om Peter Dalenius får ny chef, får kursens studierektor ny chef
Pekarexemplet (0) 18
Pekarexemplet (1) 19 Minne Med pekare: Många kan peka på samma objekt trots att själva objektet bara lagras en gång
Pekarexemplet (2) 20 Men anställd har ingen chef! Vad ska fältet ha för värde? Minne
Null-pekare 21 Objektpekare kan ha specialvärdet Pekar "ingenstans" "inte applicerbart": Noden har ingen chef "vi vet inte än" Minne Med pekare: Kan lätt ange avsaknad av värde
Null-pekare (2) 22 Vad kan man göra om pekarens värde är null? Använda själva pekarvärdet Inte använda fälten och metoderna i objektet den pekar på! Den pekar ju inte på något objekt!
Sammansättning 1 24 Anta en klass för 2D-positioner:
Sammansättning 2 25 Skapa en cirkelklass två alternativ: Implementera allt från början Använd existerande punktklassen! Sammansättning = composition
Sammansättning 3 26 Med sammansättning: En cirkel har en punkt, eller består av en punkt (och en radie) Slipper skriva om existerande kod Point kunde vara komplicerad, ha metoder som avstånd från origo, Mindre upprepning bra! Exempel i labb: Listor finns redan En kö har en lista där den kan lagra sina element
Sammansättning och delegering 27 Om man vill ge tillgång till "komponentens" funktionalitet: Delegera! Vad är cirkelns avstånd till origo? Samma som punktens, så delegera till den!
Sammansatt objektstruktur 1 28 I vissa språk: Sammansatta objekt är sammansatta i minnet "Point-delen" av en cirkel
Sammansatt objektstruktur 2 29 Men Javas objektvariabler är ju alltid pekare! Ett "sammansatt" objekt består egentligen av flera separata objekt En består av en -pekare (inte en ) en
Sammansatt objektstruktur 3 30 Konsekvenser: Som vi såg för pekare tidigare Exempel: Två cirklar kan ha samma centrumobjekt Två listor kan innehålla (pekare till) samma cirkel
jonas.kvarnstrom@liu.se 2017 Typhierarkier: Gränssnitt, ärvning, subtypspolymorfism,
Motivering 1: Verkligheten
Klasser med olikheter 33 Vi har pratat om klasser av objekt Tydliga olikheter separata klasser
Liknande objekt 34 Men om objekten är "ganska lika"? En klass: Generella motorfordon? Bra: Vi kan generalisera "Detta gäller alla motorfordon" Tre klasser: Bilar, bussar och lastbilar? Bra: Vi kan vara specifika "Detta gäller bara bussar" Fem klasser: Bil, lätt lastbil, tung lastbil, minibuss, buss?
Hierarkier av klasser 35 Vi kan ha hierarkier med både generella och specifika klasser! Fordon (gemensamma egenskaper) "is-a"-relation (en bil är en sorts motorfordon)
Hierarkier och delmängder 36 En bil är ett fordon Objekt av typ Fordon Objekt av typ Bil Alla bilar är fordon Cykel Buss Med denna hierarki: En Bil kan aldrig vara en Buss, är alltid ett Fordon
Motivation 2: Datastrukturer
Liknande datatyper (1) 38 Flera sätt att lagra listor! "Linjärt i minnet Länkad lista Snabbt att slå upp element 92000: Adress = liststart + 92000 * elementstorlek Långsamt att stoppa in ett element: Måste flytta alla efterföljande element Långsamt att slå upp element 92000: Gå till start, följ pekare 92000 gånger Snabbt att stoppa in ett element: Ändra två pekare
Liknande datatyper (2) 39 Många olika implementationer: Mycket gemensamt t.ex. vilka metoder som finns Stora skillnader i kod (metoder, fält) olika klasser
Liknande datatyper (3) 40 Om vi måste ange exakt typ för parameter, returvärde:
Duck Typing Python 41 Duck Typing: When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck James Whitcomb Riley När jag ser ett objekt med get(), set(), extend(), då kallar jag det objektet en lista Vi har en ArrayList-klass Parametertyp anges inte kolla vid körning om extend() finns!
Utan Duck Typing 42 Java Måste ange parametertyp Behöver annat sätt att ange ArrayList eller LinkedList
Hierarkier 43 Lösning: Vill ha hierarkier även här Objekt av typ List ArrayList LinkedList SkipList
Interface: Intro 45 Ett interface (gränssnitt) är specifikation utan implementation Dokumentation anger krav för alla som implementerar List Metodsignaturer: Returtyp, namn, parametrar Inga fält, ingen metodkod Gränssnitt kan inte instansieras Det finns ingen kod för dess metoder! Metoder i ett gränssnitt är alltid (underförstått): tillgängliga för alla ej implementerade här
Interface: Hierarkier 1 46 Möjliggör en hierarki av datatyper! List: Detta ska alla listor klara Säger inte hur! LinkedList: Vanlig klass som uppfyller List-specifikationen
Interface: Hierarkier 2 47 Terminologi: List är supertyp till LinkedList LinkedList är subtyp till List supertyp = supertype subtyp = subtype
Interface: Vad vinner vi? 48 Kräv mindre! Lova mindre!
Interface 2: Implementation 49 En Java-klass kan implementera ett gränssnitt Ett löfte att uppfylla vad gränssnittet lovar ("kontrakt") Kompilatorn verifierar att metoderna finns Programmeraren verifierar att kontraktet i övrigt är uppfyllt Kan ha fler metoder än gränssnittet (håller ändå vad den lovar) implementera = implement
Interface 3: Typhierarki 50 En klass kan implementera flera gränssnitt Sortable och List är supertyper till LinkedList LinkedList är en subtyp till Sortable och List
UML: Klassdiagram med gränssnitt 51 UML-diagram: Klassrelationen realisering Ett gränssnitt är bara en beskrivning Klasser realiserar gränssnittet: Ger en konkret implementation Streckad pil, tom pilspets Medlemmar visas: Där de deklareras första gången Där de implementeras
Om man har flera "klassvarianter" med gemensam bas: Oftast bör man ha ett gränssnitt, så den gemensamma basen kan användas
Objekt med flera typer 54 Ett objekt har nu flera typer Varje är också av typen och Vilka effekter får det?
Peka på en subtyp 55 En objektvariabel kan peka på objekt av godtycklig subtyp En är ju en List Så vilken typ har variabeln egentligen? En objektvariabel kan pekas om till ett objekt av annan typ Så kan variabler byta typ?
Typer: Apparent / Actual Med typhierarkier: Variabel av typ Känt av kompilatorn 56 Variabelns typ kallas static / apparent type get() add() (no impl) (no impl) Statiskt: Variabelns typ är oföränderlig get() add() print() Värdet vid exekvering blir av typen [LL-get] [LL-add] [ ] Generellt bara känt vid körning Kan ändras under körning Objektets typ kallas dynamic / actual type
Dynamisk typ: Inte känd före körning 57
Synliga (tillgängliga) medlemmar 58 Givet en variabel, vilka metoder och fält är synliga? Variabel av typ get() add() (no impl) (no impl) I Java: De som finns i variabelns (uttryckets) typ! windows.get(), windows.add() get() add() print() Värdet vid exekvering blir av typen [LL-get] [LL-add] [ ] Kompilatorn vet inte att värdet kommer att vara en LinkedList Vi kan inte anropa windows.print()!
Statisk typkontroll 59 Så typkontrollen är fortfarande statisk
Vem vet mest? 60 Men tänk om vi vet mer än kompilatorn! Vi har listor av fåglar Vi stoppar in något först i listan Vi plockar ut det Men vi vet ju vad vi stoppade in där!
Att veta mer (2) 61 Vi kan tala om för kompilatorn vad vi vet! Använd en cast Denna cast är ett löfte: Fågeln är faktiskt en uggla!" Resultatet är en ny pekare till samma objekt Inte ett nytt "konverterat" objekt! Om man ljuger: (här finns dynamisk typkontroll, dvs. vid körningen!)
Namnbindning 63 Namnbindning: Givet en identifierare (namn), vilken variabel / fält / metod / menar vi? För variabler tar kompilatorn reda på detta: Detta är statisk bindning = tidig bindning: Sker före programmet körs
Bindning av metoder 64 Att binda metodnamn till implementation: Utan typhierarkier Variabelns typ = objektets typ Statisk bindning är möjlig Med typhierarkier Variabelns typ!= objektets typ Dynamisk bindning krävs Vilken variant av add()? Måste vara ArrayList:s! Känt vid kompileringen: Namnet add() kan statiskt bindas till en funktion av kompilatorn Vilken variant av add()? ArrayList:s? LinkedList:s? Okänt vid kompileringen: Namnet add() måste dynamiskt bindas till en funktion vid körning
Metodtabeller Varje objekt känner till sin klass Varje klass känner till sin metodkod 65 Klassinfo med metodtabell Virtual method table: vtable get() add() print() [LL-get] [LL-add] [ ]
Dynamisk bindning 66 Dynamisk bindning = sen bindning = dynamisk dispatch Objektets typ avgör Objektet talar (indirekt) om för oss var implementationen finns: get() add() print() [LL-get] [LL-add] [ ] get() add() [AL-get] [AL-add]
Subtypspolymorfism 67 Typhierarkin + sen bindning ger oss Subtypspolymorfism πολυμορφισμός = som har flera former Här: Ett metodnamn, deklarerat i en typ Flera implementationer, skrivna i subtyperna Kallas ofta enbart "polymorfism" men polymorfism är egentligen bredare begrepp
Overloading 68 Kontrasteras med överlagring = ad-hoc-polymorfism Samma namn, flera implementationer (för olika argumenttyper) Inte ett OO-begrepp mer allmänt! Alla varianter är kända vid kompileringen Ger statisk bindning
Hierarkier av klasser 70 Hierarkier kan ha flera nivåer Fordon (har toppfart) "is-a"-relation (en bil är en sorts motorfordon) Motorfordon (har motorstyrka)
Hierarkier och delmängder 71 Fortfarande alla x är y : Fordon Motorfordon Alla motorfordon är fordon Cykel Bil Buss
Interface-ärvning 1: Hierarkier 72 Vi såg typhierarkier i två nivåer Gränssnitt anger funktionalitet: Vad som är gemensamt för alla listor Klasser ger oss implementationer
Interface-ärvning 2: Gemensamt 73 Men har också något gemensamt med Hur deklarerar vi en variabel som kan peka på en lista eller en mängd?
Interface-ärvning 3: En nivå till 74 Genom ytterligare en nivå!
Interface-ärvning 4 Detta är interface-ärvning 75 Collection är ett superinterface till List List utökar eller ärver från Collection List är ett underinterface till Collection List extends or inherits from Collection List is a subinterface of Collection Ärver Adderar kontrakt/löften: Collection lovar att ha en add()-metod, egna löften: List lovar också
Interface-ärvning 5: Multipel ärvning 76 Multipel ärvning tillåts för gränssnitt multipel ärvning = multiple inheritance
UML-klassdiagram: Generalisering 77 Klassrelation: Generalisering (ärvning) List specialiserar Collection (lägger till nya krav, nya metoder) Collection generaliserar List Vanlig linje, tom pilspets