Præsentation er lastning. Vent venligst

Præsentation er lastning. Vent venligst

Forelæsning Uge 12 – Mandag

Lignende præsentationer


Præsentationer af emnet: "Forelæsning Uge 12 – Mandag"— Præsentationens transcript:

1 Forelæsning Uge 12 – Mandag
Protected access Alternativ til public og private Abstrakte klasser og interfaces En abstrakt klasse er en klasse, som man ikke kan lave instanser (objekter) af En abstrakt klasse kan indeholde abstrakte metoder, hvor kun hovedet er angivet, mens implementationen (kroppen) mangler I et interface er alle metoder abstrakte Wildcards (jokere) Gør det muligt at beskrive komplicerede typebegrænsninger i forbindelse med generiske klasser Afleveringsopgave: Computerspil 3 Brug af nedarvning og dynamic method binding

2 ● Protected access Vi har tidligere set, at feltvariabler og metoder kan være private eller public De kan også være protected Det betyder at de kan tilgås fra klassen selv og alle dens subklasser public protected private protected feltvariabler Samme ulemper som public Bør aldrig bruges protected metoder Kan i nogen situationer give god mening I Java kan feltvariabler og metoder, der er protected, også tilgås fra klasser i samme programpakke (package) Det gør det mere tvivlsomt at benytte protected

3 ● Abstrakte klasser og interfaces
En abstrakt klasse er en klasse, som man ikke kan lave instanser af new operatoren kan ikke anvendes på klassen I vores Newsfeed system vil det være oplagt at erklære Post til at være en abstrakt klasse Det signalerer, at vi ikke vil lave instanser af Post, men kun instanser af dens subklasser MessagePost og PhotoPost Formålet med Post er udelukkende at samle de ting, der er fælles for MessagePost og PhotoPost, og på den måde undgå kodeduplikering og opnå større læsbarhed <<abstract>> Angiver at klassen er abstrakt Angiver, at klassen er abstrakt (rækkefølgen af public og abstract er uden betydning) public abstract class Post { ... }

4 Abstrakte metoder En abstrakt klasse kan indeholde abstrakte metoder
En abstrakt metode er en metode, der ikke er implementeret i klassen Vi angiver kun metodens hoved, mens kroppen udelades I vores Newsfeed system har vi en display metode i hver af klasserne Post, MessagePost og PhotoPost Lad os for et øjeblik antage, at display metoden i Post klassen ikke har noget fornuftigt at gøre, f.eks. fordi Post klassen ingen feltvariabler har Så kan vi erklære display metoden til at være abstrakt Betyder at implementationen af metoden overlades til subklasserne Hvis en subklasse ikke implementerer metoden, vil subklassen kun kunne kompilere, hvis den selv gøres abstrakt Dette sikrer, at alle konkrete subklasser har en implementation af metoden public abstract void display();

5 Interfaces Et interface ligner en abstrakt klasse, hvor alle metoder er abstrakte Men interfacet kan ikke have feltvariabler og konstruktører Interfacet specificerer, hvilke metoder der skal være, og angiver deres signaturer Implementationen af metoderne overlades til de klasser, der implementerer interfacet Interfaces kan nedarve fra hinanden, på samme måde som klasser, og vi kan derfor have subinterfaces og superinterfaces Vi er tidligere stødt på Comparable og Comparator, som begge er interfaces Angiver, at Comparable er et interface Signatur for compareTo metoden, som er eneste metode i interfacet alle metoder i et interface er public og abstract (hvorfor dette ikke angives) public interface Comparable<T> { int compareTo(T o); } public class Person implements Comparable<Person> { ... } Metoden implementeres i den klasse der implementerer interfacet Angiver, at klassen inplementerer interfacet

6 List interfacet Vi er også stødt på List interfacet
Sikrer at alle implementerende klasser har de basale metoder, der skal til for at håndtere en liste, og at disse har samme signatur (dvs. samme navn, samme parametre og samme returtype) Brug af interfacet gør det let at skifte mellem forskelige slags lister, f.eks. en arrayliste og en kædet liste (LinkedList) Hvis man har erklæret alle sine variable til at være af typen List (i stedet for ArrayList eller LinkedList), er det eneste der skal ændres, det sted hvor listen instantieres Her skal man udskifte new ArrayList<>() med new LinkedList<>() (eller omvendt) ……

7 Hvad opnår vi? Fælles for abstrakte klasser og interfaces
De bestemmer en type Man kan lave polymorfe metoder, som kan bruges på objekter fra alle subklasser af en abstrakt klasse alle de klasser, der implementerer et interface F.eks. kan reverse og shuffle metoderne i Collections klassen bruges på alle objektsamlinger, der implementerer List interfacet, mens min, max og sort metoderne desuden kræver, at elementtypen i objektsamlingen implementerer Comparable interfacet Nedarvning fra abstrakt eller konkret superklasse Vi arver både noget implementation og en type Klassen bliver en subtype af superklassen, og dens objekter kan bruges alle de steder superklassens objekter kan bruges Implementation af interface Vi arver kun typen (der er jo ingen implementation at arve)

8 Abstrakte klasse eller interface?
Hvorfor har Java både abstrakte klasser og interfaces? En abstrakt klasse kan indeholde implementation (og feltvariabler) ‒ det kan et interface ikke En klasse kan implementere flere interfaces ‒ men kun være (direkte) subklasse af én anden klasse Multipel nedarvning Fox, Rabbit og Hunter klasserne nedarver både fra Drawable og fra Actor Dette kan kun lade sig gøre, hvis Drawable, Actor eller begge er et interface Hvor meget er implementeret? Almindelig (konkret) klasse: alt er implementeret (100%) Interface: ingen implementation (0%) Abstrakt klasse: delvis implementation (0-100%)

9 Abstract klasse eller interface (fortsat)
Virkeligheden er (desværre) ikke helt så pæn og simpel som beskrevet ovenfor Fra og med Java 8) kan et interface indeholde implementation i form af klassemetoder og såkaldte default metoder Implementation af disse metoder nedarves til de klasser, der implementerer interfacet Default metoder er primært indført for at kunne modificere et eksisterende interface uden at ødelægge de klasser, der allerede bruger interfacet Da et interface ikke har feltvariabler og konstruktør, er det ret begrænset, hvad man kan gøre i en default metode (der er ingen tilstand at operere på) Angivelse af p's type (som oversætteren ikke længere selv kan deducere) Klassemetode i Comparator (returnerer Comparator objekt) Funktionel sortering Collections.sort(phones, Comparator. comparing( (Phone p) -> p.getPrice()) . thenComparing (p -> p.getBrand()) ); Collections.sort(phones, Comparator. comparing( p -> p.getBrand()) ); Collections.sort(phones, Comparator. comparing( p -> p.getPrice()) ); default metode i Comparator

10 Collection frameworket (udsnit)
2 forskellige slags UML pile Fuldt optrukne: nedarvning Stiplede: implementation <<interface>> Collection <<abstract class>> AbstractCollection <<interface>> Set <<interface>> List <<interface>> Queue HashSet <<interface>> SortedSet <<abstract class>> AbstractList LinkedList PriorityQueue LinkedHashSet <<interface>> NavigableSet ArrayList Vector AbstractList implementerer metoder, der er fælles for alle lister Gør det nemmere at definere sine egne List klasser, idet dele af implementationen allerede er lavet i AbstractList Analogt implementerer AbstractCollection metoder, der er fælles for alle collections TreeSet Collection frameworket 12 interfaces 35 klasser (heraf 5 abstrakte)

11 Brug af Collections og Comparable
3 forskellige slags UML pile Fuldt optrukne: nedarvning Stiplede pile: implementation Stiplede med åbent hoved: brug Collections T min(Collection<T> c) T max(Collection<T> c) void sort(List<T> l) ... <<interface>> Comparable int compareTo(T o) <<interface>> Collection boolean add(E e) boolean contains(Object o) ... <<interface>> List <<interface>> Queue <<interface>> Set Pixel Person String ArrayList LinkedList HashSet Adult Child

12 Funktionelle interfaces
Et funktionelt interface har én enkelt abstract metode apply De steder, hvor man skal bruge et objekt, hvis type er et funktionelt interface, kan man i stedet bruge en lambda java.util.function definerer en række funktionelle interfaces, bl.a. Predicate bruges til lambda'er, der returnerer en boolsk værdi BinaryOperator bruges til lambda'er, hvor de to parametre og returværdien er af samme type (f.eks. String x String -> String) Consumer bruges til lambda'er med void returtype Supplier bruges til lambda'er, der returnerer en værdi Man kan erklære variabler, hvis type er et funktionelt interface Dermed bliver det muligt at assigne lambda'er til variabler, og dermed bruge dem forskellige steder i programmet, f.eks. som parameterværdier I næste forelæsning skal vi se, at funktionelle interfaces er særdeles nyttige i forbindelse med programmering af grafiske brugergrænseflader

13 Eksempel på brug af funktionelt interface
Antag, at vi har en Person klasse med to feltvariabler name og alias, som begge er strenge Vi ønsker at definere toString metoden til at returnere disse på formen "Kurt Jensen (KJ)", hvor "Kurt Jensen" er navnet og "KJ" er aliasset Konkatenation + StringBuilder public String toString() { StringBuilder builder = new StringBuilder(); builder.append(name); builder.append(" ("); builder.append(alias); builder.append(")"); return builder.toString(); } public String toString() { return name + " (" + alias + ")"; } Konkatenation Funktionelt interface StringBuilder public String toString() { BinaryOperator<String> format = (name, alias) -> name + " (" + alias + ")"; return format.apply(name, alias); } Lokal variabel af type BinaryOperator<String> Initialiseres til lambda, der sammensætter de to input- parametre på den ønskede måde Funktionelt interface Kald af apply metoden (dvs. den konstruerede lambda) I mere komplekse situationer kan den sidste løsning have fordele, f.eks. kan vi bruge variablen format flere forskellige steder i koden

14 ● Wildcards og typebegrænsninger
Klasser med typeparametre (fx. ArrayList<E>) kaldes generiske klasser Når man (for metoderne i en generisk klasse) skal beskrive parametrenes type (og returtypen) bruges der (f.eks. i Java API'en) en speciel notation indeholdende wildcards (jokere) og typebegrænsninger Det kan være nyttigt, at kende og forstå de hyppigst forekomne wildcard konstruktioner Dem vil vi nu illustrere ved hjælp af nogle eksempler Eksempel Til brug for en grafisk brugergrænseflade vil vi gerne lave en afbildning (Map), hvor nøglerne er klasser og værdierne de farver, hvormed objekter af de forskellige klasser vises Dette kan gøres, som vist nedenfor, hvor wildcardet ? angiver, at man på dette sted kan bruge en vilkårlig type private Map<Class<?>, Color> colors; colors.put( Rabbit.class, Color.ORANGE ); colors.put( Fox.class, Color.BLUE ); Nøgler af type Class<?> Konstanter af type Color

15 Eksempler fra ArrayList<E> klassen
boolean add(E e) Tilføjer elementet e til enden af listen (nem at forstå – ingen wildcards) boolean addAll(Collection<? extends E> c) Tilføjer alle elementerne fra c Parameteren skal være en objektsamling (implementere Collection interfacet) Wildcardet ? og type betingelsen extends E angiver, at elementtypen i c kan være en vilkårlig subtype af E Sikrer at det er lovligt at tilføje elementerne i c til vores arrayliste boolean removeIf(Predicate<? super E> filter) Fjerner alle de elementer der opfylder filter Parameteren skal være et prædikat (dvs. en boolsk lambda) Input parameteren til lambda'en skal være en supertype af E Sikrer at lambda'en kan bruges på elementer af typen E, idet disse så er en subtype af lambda'ens parameter

16 Eksempler fra Collections klassen
void shuffle(List<?> list) Permuterer listens elementer Parameteren skal have en type, der implementere List interfacet Elementtypen i listen kan være vilkårlig Metoden kan bruges på alle lister, men f.eks. ikke på mængder og maps int frequency(Collection<?> c, Object o) Returnerer antallet af forekomster af objektet o i objektsamlingen c (ved brug af equals metoden) Returtypen er et heltal Første parameter skal have en type, der implementerer Collection interfacet Anden parameter kan være et vilkårligt objekt Lovligt at spørge om frekvensen af objekter, der slet ikke kan forekomme i listen (de har trivielt frequency lig med 0)

17 Eksempler fra Collections klassen (fortsat)
<T> void copy(List<? super T> dest, List<? extends T> src) Kopierer alle elementer fra src (source listen) til dest (destination listen) Begge parametre skal have typer, der implementerer List interfacet Der skal eksistere en type T, således at elementtypen i dest er en supertype af T, og elementtypen i src er en subtype af T Det betyder at elementtypen i src skal være en subtype af elementtypen i dest Sikrer at det er lovligt at indsætte elementerne

18 sort metoderne i Collections klassen
<T> void sort(List<T> list, Comparator<? super T> c) Sorterer listen ved hjælp af en comparator Første parameter skal være en liste med elementtypen T Anden parameter skal være af en type, der implementere Comparator interfacet for T (eller have en supertype, der gør det) Sikrer at T (eller en supertype af T) stiller en compare metode til rådighed for sorteringen <T extends Comparable<? super T>> void sort(List<T> list) Sorterer listen ved hjælp af den naturlige ordning Parameteren skal være en liste med elementtypen T T skal opfylder den type betingelse, der står foran "void", dvs. at T skal være en subtype af Comparable<? super T> Sikrer at T (eller en supertype af T) implementerer Comparable interfacet (og dermed stiller en naturlig ordning til rådighed for sorteringen) Yderligere info om wildcards: Link

19 ● Computerspil 3 I den tredje delaflevering skal I bruge nogle af de ting, som I har lært om nedarvning og dynamic method binding til at strukturere jeres kode I skal indføre flere forskellige slags byer/lande: BorderCity repræsenterer en grænseby, hvor man skal betale told, når man ankommer fra udlandet CapitalCity repræsenterer en hovedstad, hvor der er mange fristelser, så man (udover at modtage bonus) bruger af sin formue MafiaCountry repræsenterer et land (Sverige!), hvor man risikerer at blive overfaldet og frarøvet dele af sin formue I skal også implementere equals og hashCode metoder i Country og City klasserne Herudover skal I rette gamle fejl og mangler holde jeres dokumentation og regression tests opdaterede herunder tilføje dokumentation og regression tests for nye programdele

20 Regression tests for BorderCity / CapitalCity
Testmetoden for arrive metoden i BorderCity kan være næsten identisk med den tilsvarende testmetode i City klassen Den væsentlige forskel er, at der skal betales told, hvis spilleren kommer fra et andet land, f.eks. fra City E til City C @Test public void arriveFromOtherCountry() { for(int i=0; i<1000; i++) { Player player = new Player(new Position(cityE, cityC, 0), 250); game.getRandom().setSeed(i); // Set seed int bonus = country1.bonus(40); // Remember bonus int toll = // Calculate toll game.getRandom().setSeed(i); // Reset seed int arrive = cityC.arrive(player); // Same bonus assertEquals(arrive, ...); assertEquals(cityC.getValue(), ... ); cityC.reset(); } Skaber en spiller, der ankommer fra City E til City C med en formue på 250 € Beregn toldens størrelse Tag hensyn til tolden I bør også lave en testmetode, der tjekker, at der ikke betales told, når spilleren kommer fra samme land (f.eks. fra City D til City C) For CapitalCity klassen laves to tilsvarende testmetoder Nu skal man også tage hensyn til de penge, som spilleren bruger

21 Regression test for MafiaCountry
Testmetoden for bonus metode i MafiaCountry kan være næsten identisk med den tilsvarende testmetode i Country klassen Risikoen for at blive røvet er 20% (med mindre den ændres via Options knappen) Tabet ved røveriet er et heltal mellem 10 og 50 € (begge inklusive) @Test public void bonus(){ for(int seed = 0; seed < 1000; seed++){ game.getRandom().setSeed(seed); int robs = 0; int loss = 0; Set<Integer> values = new HashSet<>(); for(int i = 0; i<50000; i++) { int bonus = country2.bonus(80); if(bonus < 0) { robs++; assertTrue(...); loss -= bonus; values.add(-bonus); } assertEquals(...); I skal tjekke, at tabet ved røveriet ligger i intervallet [10,50] man bliver røvet ca. 20% af gangene tabet i gennemsnit udgør ca. 30 € tabet kan antage alle værdier i intervallet [10,50]

22 ● Opsummering Protected access Abstrakte klasser og interfaces
Alternativ til public og private Abstrakte klasser og interfaces En abstrakt klasse er en klasse, som man ikke kan lave instanser (objekter) af En abstrakt klasse kan indeholde abstrakte metoder, hvor kun hovedet er angivet, mens implementationen (kroppen) mangler I et interface er alle metoder abstrakte Wildcards (jokere) Gør det muligt at beskrive komplicerede typebegrænsninger i forbindelse med generiske klasser Afleveringsopgave: Computerspil 3 Brug af nedarvning og dynamic method binding

23 Det var alt for nu….. … spørgsmål


Download ppt "Forelæsning Uge 12 – Mandag"

Lignende præsentationer


Annoncer fra Google