Præsentation er lastning. Vent venligst

Præsentation er lastning. Vent venligst

GP 8, 24/10 20011 Grundlæggende programmering Efterår 2001 Forelæsning 8 onsdag 24/10 2001 kl. 9:15 – 12:00.

Lignende præsentationer


Præsentationer af emnet: "GP 8, 24/10 20011 Grundlæggende programmering Efterår 2001 Forelæsning 8 onsdag 24/10 2001 kl. 9:15 – 12:00."— Præsentationens transcript:

1 GP 8, 24/10 20011 Grundlæggende programmering Efterår 2001 Forelæsning 8 onsdag 24/10 2001 kl. 9:15 – 12:00

2 GP 8, 24/10 20012 Dagens program Det praktiske Arv (inheritance)

3 GP 8, 24/10 20013 Det praktiske LinuxLab arrangement: torsdag, 25. okt., kl. 15:15-17, LinuxLab (lok. 4.05), Linux InstallParty – får nogen til at installere Linux på din maskine. Se http://linuxlab.dk/adict/mgroup.php?organizer=LinuxLab http://linuxlab.dk/adict/mgroup.php?organizer=LinuxLab

4 GP 8, 24/10 20014 Scenarie I MiniBanken er der 3 forskellige slags Konti. –Check konti har et tilknyttet check hæfte. Der udbetales ikke renter, og det koster 50 kr. i kvartals gebyr, som trækkes når andre konti får skrevet renter til. –Opsparingskonti giver 4% i rente hvis saldo er over 75.000 kr, ellers kun 2 0 / 00. –Gevinst konti giver 2% i rente til en fælles pulje. Med 1 i 10000 vinder man hele puljen. –Mini banken har planer om at udvide fremover med nye konto typer. F.eks. Politimestrenes gevinst konti, hvor politimestrene har egen pulje, og lidt højere rentesats hvis de er over 5000 kunder med gevinst konti. Den problemstilling der skal belyses er hvordan vi kan skal skrive den metode i klassen Minibank der tilskriver rente på alle konti.

5 GP 8, 24/10 20015 Hvorfor duer den simple løsning ikke Simpel løsning, lav 3 klasser: CheckKonto, OpsparingsKonto og GevinstKonto. class MiniBank { CheckKonto [] cKonti; OpsparingsKonto[] oKonti; GevinstKonto[] gKonti;...// Osv for hver ny konto type public void tilskrivAlle(){ for (int index=0;...) cKonti[index].tilskrivRente(); for (int index=0;...) oKonti[index].tilskrivRente();... // og flere for hver ny konto type } Problemet er at når der tilføjes en ny konto type, så skal vi oprette en ny tabel, og vi skal rette i tilskrivAlle metoden.

6 GP 8, 24/10 20016 Specialisering Situationen med at der er en række klasser der har en del fællestræk (her at det er konti der kan hæves og indsættes på) og som har nogle punkter hvor de er forskellige (her rentetilskrivning) er almindeligt forekommende i programmering. Man taler om at check konto er en speciel type konto, på samme måde som en hest er en speciel type pattedyr. Objektorienterede programmeringssprog har en særlig konstruktion til at beskrive dette specialiseringsforhold. I programmeringssprog kaldes specialisering for ”nedarvning” eller ”udvidelse”.

7 GP 8, 24/10 20017 CheckKonto public class CheckKonto extends Konto{ private int checkNo; public CheckKonto(){ super(); checkNo = 0; } public void skrivCheck(double beløb){ hæv(beløb); checkNo++; } public void tilskrivRente(){ saldo = saldo - 50; } Nøgleordet ”extends” angiver at CheckKonto er en specialisering af Konto. Ud over saldo, hæv og indsæt, så udvider CheckKonto klassen med checkNo attributten og skrivCheck metoden. Som det ses på næste slide, så er der i alle Konto klasser en metode tilskriveRente(), de gør bare noget forskelligt alt efter konto type. super bruges til at sige at man ønsker at kalde en metode der er lavet i den klasse man udvider. Dette er kun nødvendigt hvis metoden har samme navn som en i den specialiserede klasse.

8 GP 8, 24/10 20018 Konto public abstract class Konto { protected double saldo; public Konto() { saldo = 0.0; } public void indsæt(double beløb) { saldo = saldo + beløb; } public void hæv(double beløb) { saldo = saldo - beløb; } abstract void tilskrivRente(); } Konto er en abstrakt klasse, som beskriver hvad der er fælles for alle konkrete kontoklasser. Dette svarer til at der ikke er væsner i den virkelige verden der kun er et Pattedyr, der er altid tale om et konkret dyr, f.eks. Hest eller Peruviansk dværglama. Hvis en klasse er erklæret abstract kan der derfor ikke instantieres vha. new. En abstrakt metode er en metode som man ikke siger hvordan virker. Dens virkemåde skal så beskrives i subklasserne (andet ord for specialiserede klasser som udvider den givne abstrakte klasse).

9 GP 8, 24/10 20019 Konto - protected public abstract class Konto { protected double saldo; public Konto() { saldo = 0.0; } public void indsæt(double beløb) { saldo = saldo + beløb; } public void hæv(double beløb) { saldo = saldo - beløb; } abstract void tilskrivRente(); } attributter (og metoder) kan erklæres protected. Det betyder at den ikke kan ses fra klienter (andre klasser som bruger Konto), men godt fra specialiseringer (klasser som udvider Konto). Hvis saldo var erklæret private, ville man ikke kunne ændre den i CheckKonto.

10 GP 8, 24/10 200110 En Minibank der virker class MiniBank { Konto [] konti;... public void tilskrivAlle(){ for (int index=0;...) konti[index].tilskrivRente(); } Hvis en objekt variabel har typen Konto, så kan den indeholde et vilkårligt konto objekt, herunder også CheckKonto objekter. Når vi kalder en metode (her tilskrivRente() ), så bruger vi altid den mest specifikke definition. Hvis konti tabellen på et sted indeholder en CheckKonto, så kalder man tilskrivRente i CheckKonto, hvis der er tale om et Gevinst konto objekt bliver tilskrivRente i Gevinst Konto kaldt. Man siger at konti variablen er polymorf, hvilket betyder flersidet. Det dækker over at den kan referere til forskellige slags objekter – som dog alle skal være instanser af en eller anden specialisering af Konto.

11 GP 8, 24/10 200111 Opsparingskonto public class OpsparingsKonto extends Konto{ public void tilskrivRente(){ if (saldo>75000) saldo = saldo + 0.04*saldo; else saldo = saldo + 0.002*saldo; } public String toString(){ return "OpsparingsKonto: " + saldo; }

12 GP 8, 24/10 200112 Gevinst konto import java.util.Random; public class GevinstKonto extends Konto { private static double pulje = 0.0; private static Random rnd = new Random(); public GevinstKonto() { super(); } public void tilskrivRente(){ double rente = 0.02 * saldo; pulje = pulje + rente; if (rnd.nextFloat() > 0.9999 ) { saldo = saldo + pulje; pulje = 0.0; } public String toString(){ return "GevistKonto: " + saldo + ”Puljen er: " + pulje; }

13 GP 8, 24/10 200113 MiniBank klassen 1) public class MiniBank { private Konto[] konti; public MiniBank(){ konti = new Konto[] {new CheckKonto(), new GevinstKonto(), new OpsparingsKonto()}; } public void udskrivAlle(){ for (int index=0; index<konti.length; index++) System.out.println( konti[index].toString() ); }

14 GP 8, 24/10 200114 MiniBank klassen 2) public void alleIndsæt(double beløb){ for (int index=0; index<konti.length; index++) konti[index].indsæt(beløb); } public void alleTilskriv(){ for (int index=0; index<konti.length; index++) konti[index].tilskrivRente(); } public void udskivCheck(){ ( (CheckKonto)konti[0]).skrivCheck(300); }

15 GP 8, 24/10 200115 Afprøvning i BlueJ BlueJ angiver nogle sammen- hænge i klasserne. Fuldt optrukne linjer med store pile angiver specialisering, med den generelle klasse for enden af pilen Stiplede linjer angiver ”bruger” hvilket ofte er klient server relationen. Pilen udpeger server.

16 GP 8, 24/10 200116 Specialisering og udvidelse Umiddelbart kan det lyde mærkeligt at en specialisering og udvidelse er samme sag. Et begreb er karakteriseret ved to aspekter –ekstension: mængden af de fænomener der der dækket ind under begrebet –intension: de egenskaber som er fælles for fænomenerne i ekstensionen. Specialisering fra Konto til CheckKonto har følgende sammenhæng i ekstension og intension –ekstensionen indskrænkes ved specialisering. Det er ikke alle konti der er check konti. –intensionen udvides ved specialisering. CheckKonti har flere fælles egenskaber en blot Konti. Man kan faktisk sige at ekstension må indskrænkes når intensionen udvides, der kommer jo flere egenskaber, og det bliver dermed vanskeligere at opfylde intensionen, og derfor er der færre fænomener der kan gøre det.

17 GP 8, 24/10 200117 Betydnings eksercits Betragt følgende to erklæringer Konto k; CheckKonto ck; Man kan så spørge hvilke af følgende kald der er OK. –k.hæv(100); –k.skrivCheck(200); –k.tilskrivRente(); –ck.hæv(100); –ck.tilskrivRente() –ck.skrivCheck(); Dette er ikke lovligt. Når man skal afgøre hvilke metoder man kan kalde, kikker man på typen af variablen k, ikke på objektet som variablen indeholder. Dette er lovligt. Idet k er af typen Konto, må man kalde tilskrivRente. Den tilskriv rente der kaldes afhænger af objektet som variablen indeholder. Generel regel om metodekald: Givet en variabel v som er erklæret af typen T. Så er kaldet v.metode() lovligt hvis metode er erklæret i T, eller en af T’s superklasser (T arver metoden)

18 GP 8, 24/10 200118 Betydnings eksercits 2 Betragt igen følgende to erklæringer Konto k; CheckKonto ck; Man kan så spørge hvilke af følgende assignments der er OK. –k = new Konto(); –k = new CheckKonto(); –k = ck; –ck = new Konto(); –ck = new CheckKonto(); –ck = k; Dette er ikke lovligt idet Konto er er abstract. Hvis Konto ikke var abstract ville det være OK. OK Konto er ikke en specialisering af CheckKonto. Ulovligt. Generel regel om assignment: en objekt variabel må indeholde objekter af dens erklærede type, eller den erklærede types subklasser. k kan indeholde noget der ikke er en CheckKonto, derfor ulovligt.

19 GP 8, 24/10 200119 Overlæsning og arv En klasse kan definere flere metoder med samme navn, bare deres metodesignatur er forskellig. Det gælder også for subklasser. En subklasse kan definere en metode med samme navn som en metode i superklassen. Begge metoder er derefter tilgængelig i subklassen (vel at mærke hvis de har forskellig metodesignatur). F.eks. class A { void m(){ System.out.println(“Metode m i klasse A”); } class B extends A { void m(String s){ System.out.println(”Metode m i klasse B” + s); } class Test { void test() { B x = new B(); x.m(); x.m(” med argument”); }

20 GP 8, 24/10 200120 Overskrivning og dynamisk metodevalg Subklasser kan overskrive (omdefinere, override) metoder i deres superklasse. Det gøres ved at definere en metode med samme metodesignatur som i superklassen. F.eks. class A { void m(){ System.out.println(“Metode m i klasse A”); } class B extends A { void m(){ System.out.println(”Metode m i klasse B”); } class Test { void test() { A x = new B(); x.m(); } Der udføres den metode, der tilhører objektets dynamiske type (actual type), dvs. den metode er tilhører klassen fra hvilken objektet blev instantieret. Dette hedder dynamisk metodevalg (dynamic dispatch). NB: Man kan ikke bare kigge på en variabels erklærede type (static type), for at finde ud af, hvilken metode vil blive invokeret.

21 GP 8, 24/10 200121 Object som rodklasse Alle klasser er subklasser af klasse Object. F.eks. class A { void m() { System.out.println(“Blablabla”); } } er en forkortelse for class A extends Object { void m(() { System.out.println(“Blablabla”); } } Object har nogle metoder, f.eks. clone, hashCode, toString. Disse metoder kan derfor anvendes på alle objekter. F.eks., med klasse A ovenfor: class Test { void test() { new A().toString(); } }

22 GP 8, 24/10 200122 Typekonvertering for referencetyper Objekter kan typekonverteres fra en referencetype til en anden referencetype ved hjælp af et cast-udtryk. F.eks. class A { void m(){ System.out.println(“Metode m i klasse A”); } class B extends A { void m(String s){ System.out.println(”Metode m i klasse B” + s);} class Test { void test() { A x = (A) new B(); B y = (B) x;} Downcasts (narrowing conversions) kan rejse en undtagelse. Upcasts (widening conversions) går altdig godt. Kun downcasts og upcasts er tilladt. Cast-delen kan udelades i tilfælde af upcasts (subtype polymorfi). Upcast (fra subklasse til superklasse) Downcast (fra superklasse til subklasse)

23 GP 8, 24/10 200123 Brug af super Man kan bruge super for at få fat i felter, metoder og konstruktorer for superklassen. Superklassens konstruktor kan kaldes med super(...), men kun som allerførste ordre i en konstruktor. Superklassens felt f kan kaldes som super.f. Superklassens metode m kan kaldes som super.m(...). Det er nyttigt hvis metoden m er blevet overskrevet i subklassen.

24 GP 8, 24/10 200124 Subtiliteter Private metoder og felter: –Hvis et felt eller en metode er private i en superklasse A, så kan det ikke benyttes i subklasser af A. –Feltet arves dog alligevel. Det findes i subklassens objekter. Ellers ville det jo ikke kunne benyttes i metoder der arves fra superklassen. Konstruktorer og arv: –Konstruktorer arves ikke. –Men det første en subklasses konstruktor gør, er at kalde en konstruktor for superklassen. Dette kan gøres eksplicit med et kald af formen super(...). –Hvis ikke det gøres eksplicit, så sker implicit et kald super() til en argumentløs konstruktor. I det tilfælde er superklassen altså nødt til at have en argumentløs konstruktor. Sådan findes automatisk hvis man ikke definerer andre konstruktorer.

25 GP 8, 24/10 200125 Subtiliteter... Felter og overskrivning: –Felter overskrives ikke. –Hvis subklassen erklærer et felt f som også findes i superklassen, så får man to felter med samme navn. –Det er næsten altid forkert og resulterer i forvirring og hovedpine! –NB: Feltet f arvet fra superklassen kan tilgås som super.f, men subklassens hedder f.

26 GP 8, 24/10 200126 Klassegrænseflader (interfaces) En klassegrænseflade (interface) kan opfattes som en ultra-abstrakt klasse: –En klassegrænseflade kan kun erklære felter der er konstante. (Modifiers final og static er underforstået, hvis de er udeladt.) –En klassegrænseflade kan kun erklære metoder der er abstrakte og synlige overalt. (Modifiers abstract og public er underforstået, hvis de er udeladt.) –En klassegrænseflade kan ikke erklære konstruktorer. En klasse kan implementere en klassegrænseflade. Dette angives ved nøgleordet implements i klassedefinitionen. –Det er angivet med nøgleordet implements i klassedefinitionen. –Klassen skal indeholde en public metode med samme metodesignatur for hver metode i klassegrænsefladen. –En klasse kan implementere flere en kun en klassegrænseflade. En klassegrænseflade kan udvide en eller flere klassegrænseflade. Dette angives ved nøgleordet extends.

27 GP 8, 24/10 200127 Nøgleord Klasser kan specialiseres. En specialiseret klasse kan udvide med flere metoder og attributter. En specialiseret klasse kan overskrive metoder. En generel klasse kan erklæres abstrakt, det betyder at man ikke kan instansiere den. En abstrakt klasse er beregnet på at blive specialiseret. En polymorf objekt variabel kan indeholde objekter af dens erklærede type eller types subklasser Alle objektvariable i Java er polymorfe. Et metodekald aktiverer altid den specialiserede metode hvis en sådan findes, ellers den arvede. I forbindelse med nedarvning introduceres protected, som siger at klienter ikke kan se metoden, men at den kan ses fra subklasser. Et interface er en abstrakt klasse hvor alle metoder er abstrakte.


Download ppt "GP 8, 24/10 20011 Grundlæggende programmering Efterår 2001 Forelæsning 8 onsdag 24/10 2001 kl. 9:15 – 12:00."

Lignende præsentationer


Annoncer fra Google