Forelæsning Uge 11 Mandag

Relaterede dokumenter
Forelæsning Uge 11 Torsdag

Forelæsning Uge 11. Nedarvning. Object klassen. Projektopgave om computerspil

Forelæsning Uge 11. Nedarvning. Object klassen. Projektopgave om computerspil

Har kun én enkelt abstract metode De steder, hvor man skal bruge et objekt, hvis type er et funktionelt interface, kan man i stedet bruge en lambda

Har kun én enkelt abstract metode De steder, hvor man skal bruge et objekt, hvis type er et funktionelt interface, kan man i stedet bruge en lambda

Forelæsning Uge 12 Torsdag

Forelæsning Uge 12 Mandag

Forelæsning Uge 6 Mandag

Forelæsning Uge 5 Mandag

COMPUTERSPIL 1. Opgave 1

COMPUTERSPIL 1. Opgave 1. Opgave 2

Forelæsning Uge 4 Mandag

Forelæsning Uge 3 Mandag

Forelæsning Uge 10 Torsdag

Forelæsning Uge 5 Mandag

Forelæsning Uge 2 Torsdag

Forelæsning Uge 4 Torsdag

Forelæsning Uge 4 Torsdag

Forelæsning Uge 5 Mandag

Forelæsning Uge 2 Torsdag

Forelæsning Uge 2 Mandag

Forelæsning Uge 3 Mandag

Forelæsning Uge 4 Mandag

Forelæsning Uge 2 Torsdag

Forelæsning Uge 5 Mandag

Forelæsning Uge 3 Mandag

Ugeseddel 4 1. marts - 8. marts

Forelæsning Uge 2 Torsdag

Forelæsning Uge 3 Mandag

Klasser og objekter. (Afsnit i manualen)

Forelæsning Uge 2 Mandag

Polymorfi. Arv (inheritance) Abstrakte klasser, substitutionsprincippet, overriding, statisk og dynamisk type. Coercion

Forelæsning Uge 4 Mandag

Forelæsning Uge 2 Mandag

dintprog Manual Revision: 1241 August 24, 2010 I Introduktion 3 1 Notation 3 II Begreber 4 2 Grundbegreber om programmering 4

Forelæsning Uge 2 Mandag

Forelæsning Uge 2 Mandag

class subklasse-navn extends superklasse-navn { } NorwaySpruce har superklassen Spruce, som igen har superklassen Tree.

dintprog Manual Revision: 731 September 30, Introduktion Notation... 3 I Begreber 4 2 Grundbegreber om programmering 4

Tree klassen fra sidste forelæsning

Forelæsning Uge 3 Torsdag

Kursus i OOP og Java. Kursus i Objektorienteret programmering i Java

DANMARKS TEKNISKE UNIVERSITET

Forelæsning Uge 3 Torsdag

Forelæsning Uge 4 Torsdag

Opfølgning på Dygtig Skildpadde (Michael) To algoritmeskabeloner

Datalogi OB, Efterår 2002 OH er, forelæsning 10/ Klasser og nedarvning

Forelæsning Uge 3 Torsdag

Forelæsning Uge 1 Torsdag

Software Construction 1. semester (SWC) januar 2014 Spørgsmål 1

Software Construction 1 semester (SWC) Spørgsmål 1

DRONNINGER (QUEENS) Opgave 1

b) Udvid din implementation af forme til at understøtte.equals. To objekter af samme form er ens hvis de har samme værdier i felterne.

Forelæsning Uge 1 Torsdag

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 4

Virkefeltsregler i Java

Eksempel: Skat i år 2000

Forelæsning Uge 6 Mandag

Løsning af møntproblemet

Klasser og nedarvning

class Time { int hours, min; } } Time t1; // Erklær variabel af type Time class Time1 { public static void main(string[] args) { Time t1; t1.

Skriftlig eksamen i Datalogi

AAU, Programmering i Java Intern skriftlig prøve 18. maj 2007

Indledning. Hvorfor det forholder sig sådan har jeg en masse idéer om, men det bliver for meget at komme ind på her. God fornøjelse med læsningen.

Forelæsning Uge 9 Mandag

SWC eksamens-spørgsmål. Oversigt

Forelæsning Uge 3 Torsdag

Forelæsning Uge 6 Mandag

Java Klasse nedarvninger

Rename og redefine. Abstrakte klasser. Dynamisk binding.

Fundamentale sprogbegreber

Klasser. Grundlæggende Programmering med Projekt. Peter Sestoft Tirsdag 2. september (Tak til Jakob Bardram for nogle slides) Dagens begreber

Om binære søgetræer i Java

Hvad er Objekter - Programmering

Forelæsning Uge 10 Mandag

Videregående Programmering Obligatorisk opgave - 3. semester, efterår 2004

Abstrakte datatyper C#-version

University of Southern Denmark Syddansk Universitet. DM503 Forelæsning 11

Forelæsning Uge 3 Torsdag

Forelæsning Uge 10. Opremsningstyper. Forskellige teknikker til test og debugging. Afleveringsopgave: Debugging + Test.

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 3

Aritmetiske Forelæsning Pr ogrammering operatorer tir 1999 sda præcedens september 1999 Logiske Sammenligningsoperatorer operatorer præcedens

Skriftlig eksamen i Datalogi

Forelæsning Uge 6 Mandag

DM01 DM Obl. Afl. Jacob Christiansen, , D12, Elias 18/ Side 1 af 11

Programmering 1999 KVL Side 5-4. Klassen Time: metoder. Metoder i objektet giver mulighed for at ændre tilstanden, eller kigge på tilstanden.

University of Southern Denmark Syddansk Universitet. DM502 Forelæsning 2

Skriftlig eksamen i Datalogi

Objektsamlinger med et fast (på forhånd kendt) antal elementer Velkendt fra mange andre programmeringssprog

Vejledende løsninger

Databaseadgang fra Java

Forelæsning Uge 9 Mandag

DM507 Algoritmer og datastrukturer

Forelæsning Uge 6 Mandag

DM507 Algoritmer og datastrukturer

Tabelbegrebet. Klassediagrammer (III) Oversigt. Anvendelse af Tabeller. Tabeller og qualified associations

Forelæsning Uge 10. Opremsningstyper. Forskellige teknikker til test og debugging. Afleveringsopgave: Debugging + Test.

Hashing og hashtabeller

Objektsamlinger med et fast (på forhånd kendt) antal elementer Velkendt fra mange andre programmeringssprog

Stakke, køer og lidt om hægtede lister - kapitel 16 og 17

Transkript:

Forelæsning Uge 11 Mandag Nedarvning En klasse kan være en subklasse af en anden Det betyder at subklassen arver superklassens feltvariabler og metoder Object klassen Superklasse for alle klasser Indeholder en række nyttige metoder, bl.a. getclass, tostring, equals og hashcode Afleveringsopgave: Computerspil 2 Dokumentation og test af de klasser, som I har implementeret i den første delaflevering

Nedarvning (subklasser) Vi vil gerne modellere et simpelt nyhedssystem med to slags meddelelser Almindelige tekstmeddelelse (MessagePost) Fotomeddelelse (PhotoPost) Uden brug af nedarvning ser det sådan ud Feltvariabler Metoder Stort overlap, men også forskelle 2

Dublering af kode MessagePost og PhotoPost ligner hinanden Store dele af de to klassers Java kode er identiske Det gør koden svær at overskue og vanskelig at vedligeholde Der opstår let fejl og inkonsistens, f.eks. når man ændrer noget i den ene klasse, men glemmer at rette i den anden Også dublering i NewsFeed klassen Den har to arraylister Mange metoder gennemløber begge lister (dubleret kode) Det er endnu værre, hvis vi i stedet for to slags postings har mange forskellige slags 3

Brug af nedarvning (subklasser) Vi kan i stedet lave en Post klasse, som har MessagePost og PhotoPost som subklasser En subklasse arver alle feltvariabler og metoder fra den oprindelig klasse Superklasse Vi har nu kun én arrayliste i NewsFeed klassen Bemærk formen på pilehovederne Fælles feltvariabler og metoder postings Post Subklasser Forskellige feltvariabler og metoder MessagePost PhotoPost MessagePost Nemmere at overskue Ingen kodedublering 4

Nedarvning i Java public class Post { Superklasse private String username; private long timestamp; private int likes; private ArrayList<String> comments; public Post(String author) { username = author; timestamp = System.currentTimeMillis(); likes = 0; comments = new ArrayList<>(); // Methods omitted public class MessagePost extends Post { private String message; Feltvariabel I tilgift til de 4, der nedarves Konstruktør Initialiserer feltvariablen Kalder superklassens konstruktør, så de fire nedarvede feltvariabler kan blive initialiseret 4 feltvariabler Konstruktør Initialiserer de 4 feltvariabler Angiver at klassen er en subklasse af Post Subklasse public MessagePost(String author, String text) { super(author); message = text; // Methods omitted 5

Access rettigheder public class Post { Superklasse private String username; private long timestamp; private int likes; private ArrayList<String> comments; public Post(String author) { username = author; timestamp = System.currentTimeMillis(); likes = 0; comments = new ArrayList<>(); // Methods omitted public class MessagePost extends Post { private String message; Java kræver at første sætning i en subklasses konstruktør er et kald til superklassens konstruktør Hvis dette ikke er tilfældet, indsætter compileren et sådant kald (uden parametre) De 4 feltvariabler i superklassen er private Subklassen kan (som alle andre klasser) kun tilgå dem via public accessor og mutator metoder defineret i superklassen public metoder fra superklassen kan kaldes i subklassen som om de var lokale Uden brug af dot notation methodname(args) Subklasse public MessagePost(String author, String text) { super(author); message = text; // Methods omitted 6

Subtyper Alle objekt klasser bestemmer en type Når en klasse B er en subklasse af klassen A, siger vi at typen B er en subtype af typen A (som er en supertype af typen B) De steder, hvor der skal bruges et objekt af typen A, kan man i stedet bruge et objekt af en subtype B A a; B b; Assignments a = b; Parameterværdier public void pip(a param) {...; Returværdier Elementer i objektsamlinger pip(b); Ovenstående er kendt som Liskovs substitutionsprincip Vi har tidligere sagt at typerne skal matche (for assignments, parametre, returværdier og objektsamlinger) public A pop() {... return b;... ArrayList<A> list; list.add(b); Mere præcist betyder det, at typen af udtrykket skal være den samme som variablens/parameterens type eller være en subtype heraf 7

NewsFeed klassen public class NewsFeed { private ArrayList<Post> posts; public NewsFeed() { posts = new ArrayList<>(); public void addpost(post post) { posts.add(post); public void show() { for(post post : posts) { post.display(); System.out.println(); Feltvariabel Arrayliste med elementtypen Post Elementerne i listen vil være af typen MessagePost eller PhotoPost Konstruktør Initialiserer feltvariablen Metode til indsættelse af postings Bemærk at parameteren er af typen Post Argumenter af typen MessagePost og PhotoPost er også lovlige Metode til udskrift af alle postings For-each løkken løber arraylisten igennem og udskriver de enkelte elementer ved hjælp af display metoden fra Post klassen 8

Statisk og dynamisk type Lad os se lidt nærmere på show metoden fra foregående slide public void show() { for(post post : posts) { post.display(); System.out.println(); Den lokale variabel post er erklæret til at have typen Post Vi siger derfor, at den statiske type for variablen post er Post De objekter som variablen post vil pege på er af typen MessagePost eller typen PhotoPost Vi siger derfor, at den dynamiske type for post er MessagePost, når post peger på et MessagePost objekt PhotoPost, når post peger på et PhotoPost objekt Opsummering Den statiske type bestemmes af variablens erklæring Den dynamiske type bestemmes af det objekt, som variablen pt peger på Den dynamiske type er altid en subtype af den statiske type (eller identisk med denne) 9

Typeskift (type cast) Vehicle v1 = new Vehicle(); Vehicle v2 = new Car(); Vehicle v3 = new Bicycle(); Vehicle v = new Car(); Car c = new Car(); v = c; // Lovligt c = v; // Ulovligt, compile-time fejl c = (Car) v; // Lovligt Javas variabler er polymorfe De kan antage værdier af forskellig type Polymorf kan antage forskellige former Type cast Typen af udtrykket ændres til at være Car Kun muligt, hvis den dynamiske type af v er Car (eller en subtype af Car) Ellers får man en run-time fejl Objektet v ændres ikke på nogen måde ved et type cast Det eneste, der ændres, er typen af udtrykket på højresiden af assignmentet 10

Nedarvning i flere niveauer En subklasse kan igen have subklasser, osv. Dog klassen er en Direkte subklasse af Mammal klassen Subklasse af Animal klassen (subklasse relationen er transitiv) Subklasse af sig selv (subklasse relationen er refleksiv) Direkte superklasse for Poodle og Dalmatian klasserne Superklasse af sig selv (superklasse relationen er refleksiv og transitiv) 11

Klassediagram for brug af Comparable Collections T min(collection<t> c) T max(collection<t> c) void sort(list<t> l)... <<interface>> Collection boolean add(e e) boolean contains(object o)... 3 forskellige slags UML pile Fuldt optrukne pile med lukket hoved angiver nedarvning mellem klasser/interfaces Stiplede pile med lukket hoved angiver implementation af interface Stiplede pile med åbent hoved angiver brug (uses) <<interface>> Comparable int compareto(t o) <<interface>> List <<interface>> Queue <<interface>> Set Pixel Person String ArrayList HashSet LinkedList Adult Child 12

Metoder i subklasser Lad os nu kigge lidt nærmere på metoder i super- og subklasser Post klassen har en display metode, der udskriver information om klassens tilstand display metoden har kun adgang til feltvariabler i Post klassen Hvad gør vi, hvis vi gerne vil udskrive information om subklassernes feltvariabler? Fælles feltvariabler og metoder Sidebemærkning (om cohesion) display metoden udskriver klassens tilstand Det ville være bedre at have en tostring metode, der returnerer en tekststreng Så kan man på kaldstedet selv bestemme, hvad man vil gøre ved tekststrengen Forskellige feltvariabler og metoder 13

Situationen er som vist nedenfor public void display() { System.out.println( username ); System.out.print(timeString( timestamp )); if( likes > 0) { System.out.println(likes + " people like this."); else { System.out.println(); if( comments.isempty()) { System.out.println("No comments."); else { System.out.println(comments.size() + " comment(s)."); public void show() { for(post post : posts) { post.display (); System.out.println(); Newsfeed Post Post klassens display metode kender ikke de feltvariabler, der ligger i subklasserne, og kan derfor ikke udskrive information om disse 14

Første løsningsforslag (virker ikke) Vi kan flytte display metoden til de to subklasser Metoderne har kun adgang til superklassens feltvariabler via acces metoder Det giver massiv kodedublering Vi får en compile-time fejl i NewsFeed klassen Den lokale variabel post har Post som sin statiske type public void show() { for( Post post : posts) { post.display (); System.out.println(); Newsfeed Oversætteren bruger altid den statiske type og kigger derfor (uden held) i Post klassen (og dens superklasser) for at finde display metoden Det hjælper ikke, at alle subklasserne har en display metode xxx 15

Korrekt løsning Vi har både en display metode i superklassen og i de to subklasser Vi undgår kodedublering display metoderne i subklasserne kalder display metoden i superklassen og har (via den) adgang til superklassens feltvariabler uden brug af acces metoder public void display() { super.display(); System.out.println(message); MessagePost public void display() { super.display(); System.out.println(filename); System.out.println(caption); PhotoPost Kaldet af super behøver ikke at være i første linje og det kan helt mangle (uden at compileren indsætter det) Det er kun nødvendigt at bruge ordet super, når samme metodenavn bruges i super- og subklasse 16

Statiske type Oversætteren bruger den statiske type, dvs. typen fra variablens erklæring Den lokale variabel post er erklæret til at være af typen Post Oversætteren kigger derfor i Post klassen for at finde display metoden (og finder den) public void show() { for( Post post : posts) { post.display (); System.out.println(); Newsfeed 17

Dynamiske type Under programudførelsen bruges den dynamiske type, dvs. typen af variablens aktuelle værdi Når den aktuelle værdi af post er en MessagePost kaldes displaymetoden fra MessagePost Når den aktuelle værdi af post er en PhotoPost kaldes display metoden fra PhotoPost public void show() { for(post post : posts) { post.display (); System.out.println(); Newsfeed De to subklasser overskriver superklassens display metode med deres egne udgaver af metoden På engelsk: override underkende/tilsidesætte De nye metoder skal have samme signatur som den de overskriver Når man overskriver en metode, bør man af hensyn til compileren (og dem der læser koden) skrive @Override i linjen over metodesignaturen Så får man en advarsel, hvis signaturerne ikke matcher 18

Simpelt eksempel (kun en klasse) p.display(); Ingen nedarvning Ingen overskrivning PhotoPost p; Vi bestemmer variablens dynamiske type Find det objekt, som variablen peger på Find objektets type (klasse) display metoden søges i PhotoPost og findes der 19

Nedarvning uden overskrivning p.display(); PhotoPost p; Vi bestemmer variablens dynamiske type Find det objekt, som variablen peger på Find objektets type (klasse) display metoden søges i PhotoPost (uden held) display metoden søges i superklasserne (efter tur) og findes i Post 20

Nedarvning med overskrivning p.display(); Den statiske type er nu Post Post p; display Vi bestemmer variablens dynamiske type Find det objekt, som variablen peger på Find objektets type (klasse) display metoden søges i PhotoPost og findes der 21

Dynamic method lookup (opsummering) Under udførslen findes den rigtige metode ved at bestemme variablens dynamiske type søge metoden i denne klasse eller i en superklasse af den Oversætteren har tjekket, at metoden findes i variablens statiske type (eller en af dennes superklasser) Den dynamiske type er en subtype af den statiske type Vi er derfor sikre på at finde metoden Den er i den statiske type eller en af dennes superklasser Kan være overskrevet i en subtype heraf Ovenstående er kendt som dynamic method lookup Spiller en essentiel rolle i anvendelsen af subklasser Tillader at de enkelte subklasser kan lave deres egne specialtilpassede versioner af en metode Eksempel på responsibility-driven design 22

Polymorfi Betyder at noget kan antage forskellige former Vi har tidligere set, at Javas variabler er polymorfe De kan antage værdier af forskellig type Vi har nu set, at også Javas metodekald er polymorfe Et metodekald kan aktivere metoder i forskellige klasser (typer) public void show() { for(post post : posts) { post.display (); System.out.println(); Newsfeed Metodekaldet aktiverer sommetider display metoden i MessagePost og sommetider display metoden i PhotoPost 23

Object klassen Alle klasser i Java er subklasser af Object klassen Object klassen indeholder en række nyttige metoder, som de øvrige klasser nedarver (eller overskriver) getclass metoden fortæller, hvilken klasse objektet tilhører tostring metoden returnerer en tekstrepræsentation af det pågældende objekt equals metoden tjekker om to objekter "ligner hinanden" hashcode metoden beregner en hashkode 24

getclass metoden og instanceof Man kan undersøge et objekts klasse på forskellige vis Ved hjælp af det reserverede ord instanceof Her testes om objektet tilhører den angivne klasse eller en subklasse heraf Vehicle v; Car c; if( v instanceof Car){ c = (Car) v; Ved hjælp af getclass metoden (fra Object klassen) Metoden returnerer et objekt fra klassen Class I et kørende program har hver type (også de primitive) et (og kun et) tilhørende objekt i Class Class er en parametriseret type og objektet for klassen A tilhører Class<A> if( x.getclass() == y.getclass() ) {... Man kan også skrive som vist nedenfor (hvor Person.class angiver Person klassens objekt i klassen Class<Person>) if( x.getclass() == Person.class ) {... I begge tilfælde skal klasserne matche eksakt det er ikke nok at den ene er en subklasse af den anden (som ved brug af instanceof) 25

tostring metoden Metoden bruges bl.a. i print og prinln metoderne Hvis argumentet til metoderne ikke allerede er en tekststreng, bruges tostring til at konvertere argumentet til en tekststreng Det er også tostring metoden, der bruges, når den ene side af en + operation skal konverteres til en tekststreng I Object klassen er tostring metoden defineret til at returnere Person@19bb25a, hvor Person er klassens navn og 19bb25a er den hexadecimale repræsentation af hashkoden (som vi vender tilbage til) Hashkoden giver ikke ret meget interessant information String klassen redefinerer metoden til at returnere værdien af tekststrengen (i stedet for String@19bb25a) Jeres egne klasser bør også redefinere tostring metoden For personklassen kan man f.eks. returnere tekststrengen Cecilie:18, hvor Cecilie er personens navn og 18 er personens alder I køreprøveopgaverne blev I altid bedt om at redefinere tostring metoden (for den simple af klasserne) 26

StringBuilder klassen (fra java.lang) Alternativ til konkatenation af strenge ved hjælp af + operatoren Lad os, som et eksempel, lave en tostring metoden for Post klassen Lokal variabel af type StringBuilder Tilføj de ønskede strenge ved hjælp af append metoden i StringBuilder Returner den opbyggede streng ved hjælp af tostring metoden i StringBuilder public String tostring() { StringBuilder builder = new StringBuilder(); builder.append(username); builder.append(timestring( timestamp )); if( likes > 0) { builder.append(likes + "" people like like this."); Linjeskift else { builder.append('\n'); ); if( comments.isempty()) { builder.append("no comments."); else { builder.append(comments.size() + " comment(s)."); return builder.tostring(); 27

equals metoden Metoden bruges bl.a. i collections til at afgøre om et givet element allerede er indeholdt i en mængde (Set) for en mængde vil et kald add(elem) kun tilføje elementet, hvis der ikke eksisterer et element e i mængden, så elem.equals(e) er sand I Object klassen er equals metoden defineret ved hjælp af == Det betyder at e1.equals(e2) kun evaluerer til sand, hvis de to objekter er identiske (e1 == e2) Dette er ofte for restriktivt String klassen redefinerer metoden til at tjekke om de to tekststrenge er ens, dvs. indeholder de samme tegn (i samme rækkefølge) Jeres egne klasser bør også redefinere equals metoden Det kræves at equals er en ækvivalensrelation Refleksiv: x.equals(x) for alle x Symmetrisk: x.equals(y) y.equals(x) for alle x,y Transitiv: x.equals(y) y.equals(z) x.equals(z) for alle x,y,z Teknisk: x!= null!x.equals(null) for all x 28

Redefinering af equals metoden For Person klassen kan man definere equals som følger Optimalisering null? Rigtig klasse? Type cast Sammenlign (udvalgte) feltvariabler public boolean equals(object otherobject) { if( this = = otherobject ) {return true; if( otherobject = = null ){return false; if( getclass()!= otherobject.getclass() ) {return false; Person other = (Person) otherobject; return name.equals(other.name) && age == other.age; I subklassen Child kan man definere equals som følger Kald af equals i superklassen korrekt klasse mv superklassens feltvariabler Tjek af egne feltvariabler public class Child extends Person { private int nooftoys; Feltvariabel... public boolean equals(otherobject) { if(!super.equals(otherobject) ) {return false; return nooftoys = = otherobject.nooftoys;... 29

hashcode metoden Metoden returnerer en hashkode for objektet Hashkoder bruges som nøgler i såkaldte hashtabeller, f.eks. i klasserne HashSet og HashMap Det kræves, at hashcode er konsistent med equals x.equals(y) hashcode(x) == hashcode(y) Derudover bør hashcode være konstrueret således, at der for to forskellige objekter (! x.equals(y)) er lille sandsynlighed for at deres hashkoder kolliderer (hashcode(x) == hashcode(y)) I Object klassen er hashcode metoden defineret som objektets memory adresse Dermed er det nemt at se, at hashcode er konsistent med equals Hvis jeres egne klasser redefinerer equals metoden, vil det normalt også være nødvendigt at redefinere hashcode metoden Dette gøres for at sikre at ovenstående betingelse stadig er opfyldt 30

Hashkoder for tekststrenge Det er en hel videnskab at definere hashkoder, hvor der er så få kollisioner som muligt Lad os starte med at se, hvordan hashcode kan defineres i String klassen s er en feltvariabel, der indeholder værdien af tekststrengen public int hashcode() { int hc = 0; for( int i = 0; i < s.length(); i++) { hc = hc 31 + * s.charat(i); hc + s.charat(i); return hc; hashcode("eat") = 'e' 31 2 + *'a' 'e' + + 't' 31 = * 101 'a' + + 97 't' + 116 = 100184 = 314 hashcode("tea") = 't' 31 2 + *'e' 't' + + 'a' 31 = * 116 'e' + + 101 'a' + 97 = 114704 = 314 31

Hashkoder for jeres egne klasser For Person klassen kan man definere hashcode som følger Vi bruger kun de feltvariabler, som tjekkes i equals metoden Primitive værdier konverteres først til deres wrapper type Hashkoderne multipliceres med forskellige primtal før de adderes public int hashcode() { return 11 * name.hashcode() + 13 * new Integer(age).hashCode(); I subklassen Child kan man definere hashcode som følger Hashkode for superklassens feltvariabler Hashkode for egne feltvariabler public class Child extends Person { private int nooftoys; Feltvariabel... public int hashcode() { return super.hashcode() + 17 * new Integer(noOfToys).hashCode();... 32

Afleveringsopgave: Computerspil 2 I den anden delaflevering skal I bruge nogle af de ting, som I har lært om dokumentation og test, på de fire klasser, som I har implementeret i den første delaflevering Gennemgå de fire klasser, og tilføj dokumentation, således at den er helt i top og følger de retningslinjer, der gives i BlueJ bogen (herunder specielt afsnit 6.11, afsnit 9.7 og Appendix I) Lav velvalgte regression tests for de fire klasser I skal både teste, hvad der normalt sker, og hvad der sker i specialtilfælde og tæt ved grænseværdier Husk, at der skal være både positive og negative tests Det er dog ikke nødvendigt at lave testmetoder for trivielle accessor og mutator metoder, der blot returnerer/ændrer en enkelt feltvariabel uden at gøre andet Herudover skal I rette de fejl og mangler, som instruktoren har påpeget i jeres første delaflevering 33

Dokumentation af Road klassen Kommentar for klassen Kommentar for feltvariablerne Kommentar for konstruktøren Kommentar for metoden /** * Represents a road (between to cities). * A road is one-directional. This means that we may have a road from * City A to City B, without having a road from City B to City A. * * @author Kurt Jensen. * @version April 2017. */ public class Road implements Comparable<Road> { /** References to the cities connected by this Road */ private City from, to; /** Length of this Road. */ private int length; /** * Creates a new Road object. * @param from City where this Road starts. * @param to City where this Road ends. * @param length Length of this Road object. */ public Road(City from, City to, int length){ this.from = from; this.to = to; this.length = length; Husk også at indsætte kommentarer passende steder i kompleks kode For testklasser og testmetode behøver I ikke at lave klasseog metodekommentarer /** * Returns a reference to the City where this Road starts. * @return from city. */ public City getfrom(){ return from;... 34

Documentation view Husk at kontrollere, at resultatet er fornuftigt Skal give relevant og letlæselig information Til brugere, der ikke kender implementationen af jeres klasser. 35

Test All: Test of Road klassen Fra den generelle Test Fixture kan I "stjæle" import sætningerne Feltvariablerne for landet og byerne Erklæringerne i setup metoden (idet vi dog sætter netværket til null, da vi ikke skal bruge det) For overskuelighedens skyld bør I fjerne de dele, som I ikke bruger I skal lave en testmetode for hver (ikke triviel) konstruktør/metode Hver testmetode tester flere forskellige ting (via forskellige assertions) Testmetode for konstruktøren Vi skaber et Road objekt og tjekker at feltvariablerne initialiseres korrekt Testmetode for compareto Vi skaber veje mellem byerne fra vores Test Fxiture (setup metode) og tjekker at compareto returnerer værdier med korrekt fortegn import static org.junit.assert.*; import org.junit.after; import org.junit.before; import org.junit.test; public class RoadTest { private Country country1, country2; private City citya, cityb, cityc; @Before public void setup() { country1 = new Country("Country 1", null); citya = new City("City A", 80, country1); cityb =... cityc =...... @Test public void constructor() { Road road = new Road(cityA, cityb, 4); assertequals(road.getfrom(), citya);... @Test public void compareto() { Road road1 = new Road(cityA, cityb, 0); Road road2 = new Road(cityA, cityc, 0); Road road3 = new Road(cityB, citya, 0); asserttrue(road1.compareto(road2) < 0);... asserttrue(road2.compareto(road1) > 0);... assertequals(road1.compareto(road1), 0); 36

Test af Position klassen Disse ting kan I (som før) stjæle fra den generelle Test Fixture Sætningerne i de to grønne bokse skal I selv tilføje Fjern de ting i Test Fixturen, som ikke bruges Som før skal I lave en testmetode for hver (ikke triviel) konstruktør/ metode Hver testmetode tester flere forskellige ting (via forskellige assertions) Testmetode for konstruktøren Vi tjekker at feltvariablerne initialiseres korrekt Testmetode for hasarrived metoden Hvor mange gange skal move metoden kaldes før hasarrived returnerer true? Når man har lavet et par optagelser af testmetoder og set, hvordan de ser ud, er det langt hurtigere at skrive testmetoderne selv import... public class PositionTest { private Country country1; private City citya, cityb; private Position pos; @Before public void setup() { country1 = new Country("Country 1", null); citya =... cityb =... pos = new Position(cityA, cityb, 3); @Test public void constructor() { assertequals(pos.getfrom(), citya);...... @Test public void hasarrived() { assertfalse(pos.hasarrived()); pos.move(); assertfalse(pos.hasarrived());... pos.move(); asserttrue(pos.hasarrived()); Spilleren står i citya og er på vej mod cityb, som kan nås i 3 skridt 37

Test af Position klassen (fortsat) Testmetode for move Kald move metoden et antal gange og test hver gang værdierne af distance og returværdi Husk at teste tilfældet, hvor distance er nul Testmetode for turnaround A. move + turnaround B. move + turnaround C. turnaround Efter hvert kald af turnaround tjekkes, at de 4 feltvariablerne i pos har de korrekte værdier Hvis man højreklikker testklassen og vælger Test All får man @Test public void move() { assertequals(pos.getdistance(), 3); asserttrue(pos.move()); assertequals(pos.getdistance(), 2;... @Test public void turnaround() { pos.move(); A A pos.turnaround(); assertequals(pos.getfrom(), cityb);... pos.move(); B B pos.turnaround(); assertequals(pos.getfrom() ==...... Cpos.turnAround(); C assertequals(pos.getfrom() ==......; 38

Assertions Assertions kan skrives på flere forskellige måder assertequals, asserttrue, eller assertfalse Det er lige meget hvilken af de tre assert metoder, man bruger assertequals bruger (som navnet antyder) equals metoden til at sammenligne de to værdier (af en Objekt type) Disse tre sætninger er ækvivalente assertequals(false, pos.hasarrived()); asserttrue(!pos.hasarrived()); assertfalse(pos.hasarrived()); Disse to sætninger er ækvivalente assertequals(citya, pos.getfrom()); asserttrue(citya.equals(pos.getfrom())); Bemærk at knappen Run Tests kun tester metoderne i de test klasser, der allerede er succesfuldt kompileret 39

Test af metoder med tilfældige værdier Når man skal teste arrive metoden i City klassen kan det være nyttigt at resette den seed værdi som Random objektet bruger På den måde kan man finde ud af hvad bonus metoden returnerer, når den kaldes inde fra arrive @Test Test at returværdi og værdien af value er korrekt public void arrive(){ game.getrandom().setseed(0); // Set seed int bonus = country1.bonus(80); // Remember bonus game.getrandom().setseed(0); // Reset seed int arrive = citya.arrive(); // Same bonus assertequals(arrive,...); assertequals(citya.getvalue(),...); Man kan også proppe det hele ind i en for løkke og dermed teste mange forskellige seed værdier Tager ikke meget længere tid Det er opsætningen af Test Fixturen, der er dyr Som ovenfor, bortset fra, at seed nu resettes til i Husk at resette byen mellem de enkelte tests @Test public void arrive(){ for(int i=0; i<1000; i++) { // Try different seeds game.getrandom().setseed(i); // Set seed int bonus = country1.bonus(80); // Remember bonus game.getrandom().setseed(i); // Reset seed int arrive = citya.arrive(); // Same bonus assertequals(arrive,...); assertequals(citya.getvalue(),...); citya.reset(); 40

Eksempler på testmetoder for Country arrive kaldes 3 gange for hver by Så er man nogenlunde sikker på at byens værdi er ændret @Test public void reset() { citya.arrive(); citya.arrive(); citya.arrive(); citye.arrive(); citye.arrive(); citye.arrive(); int valuee = citye.getvalue(); // Remember value of citye country1.reset(); assertequals(citya.getvalue(), 80); // citya is reset assertequals(citye.getvalue(), valuee); // citye is not reset @Test public void bonus() { for(int seed = 0; seed < 1000; seed++) { // Try 1000 different seeds game.getrandom().setseed(seed); int sum = 0; Set<Integer> values = new HashSet<>(); for(int i = 0; i < 10000; i++) { // Call method 10000 times int bonus = country1.bonus(80); asserttrue(...<= bonus && bonus <=...); // Correct interval sum += bonus; values.add(bonus); asserttrue(... < sum && sum <...); // Average close to 40 assertequals(values.size(),...); // All values returned Man bør lave tilsvarende tests for grænsetilfældene, hvor bonus kaldes med parametrene 0 og 1 41

Opsummering Nedarvning Subklasser Forskellen på en variabels statiske og dynamiske type Subtyper og Liskovs substitutionsprincip Typeskift (type cast) Metoder i subklasser Dynamic method lookup i forbindelse med nedarvning og overskrivning Object klassen Superklasse for alle klasser Indeholder en række nyttige metoder, bl.a. getclass, tostring, equals og hashcode Afleveringsopgave: Computerspil 2 Dokumentation og test af de klasser, som I har implementeret i de første delaflevering Bemærk vores automatiske værktøj til debugning af Computerspilsprojektet Kan anvendes i delaflevering 1 og 3 Kan hjælpe med at finde de klasser, der får testmetoderne (i CG1 opg. 10 og CG3 opg. 6) til at fejle Kan også hjælpe med at finde de metoder/ konstruktører, der fejler 42

Det var alt for nu.. spørgsmål 43