1 / 27

Grundlæggende programmering Efterår 2001

Grundlæggende programmering Efterår 2001. Forelæsning 8 onsdag 24/10 2001 kl. 9:15 – 12:00. Dagens program. Det praktiske Arv (inheritance). Det praktiske.

candid
Télécharger la présentation

Grundlæggende programmering Efterår 2001

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Grundlæggende programmeringEfterår 2001 Forelæsning 8 onsdag 24/10 2001 kl. 9:15 – 12:00

  2. Dagens program • Det praktiske • Arv (inheritance)

  3. 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

  4. 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. 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. 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. 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; } } CheckKonto 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. 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. 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.

  8. 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 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. 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. class MiniBank { Konto [] konti; ... public void tilskrivAlle(){ for (int index=0;...) konti[index].tilskrivRente(); } } En Minibank der virker 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. 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; } } Opsparingskonto

  12. 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. 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. 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. 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. 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. Specialisering og udvidelse

  17. 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(); Betydnings eksercits 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) 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.

  18. 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; Betydnings eksercits 2 Generel regel om assignment: en objekt variabel må indeholde objekter af dens erklærede type, eller den erklærede types subklasser. 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. k kan indeholde noget der ikke er en CheckKonto, derfor ulovligt.

  19. 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. 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. Object som rodklasse • Alle klasser er subklasser af klasse Object. • F.eks.class A { void m() { System.out.println(“Blablabla”); }}er en forkortelse forclass 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. 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. 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. 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. 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. 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. 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. Nøgleord

More Related