310 likes | 423 Views
Grundlæggende programmering Efterår 2001. Forelæsning 5 onsdag 26/9 2001 kl. 9:15 – 12:00. Dagens program. Det praktiske Syntaks Objekter, referencer og variable Metodeinvokeringer, kaldstak. Det praktiske.
E N D
Grundlæggende programmeringEfterår 2001 Forelæsning 5 onsdag 26/9 2001 kl. 9:15 – 12:00
Dagens program • Det praktiske • Syntaks • Objekter, referencer og variable • Metodeinvokeringer, kaldstak
Det praktiske • LinuxLab arrangement: torsdag, 27. sep., kl. 15:15-17, LinuxLab (lok. 4.05), ”Java programming on Linux”; se http://linuxlab.dk/adict/mgroup.php?organizer=LinuxLab • Opdateret gp.jar: Brug den nyeste version af gp.jar (se hjemmesiden og it-c.courses.GP for oplysninger). • Ugeseddel 5: Ugeseddel 5 er noten (og derfor pensum) for dagens forelæsning. Kom velforberedt til øvelserne næste uge: læs ugesedlen og start at arbejde på opgaverne inden øvelserne.
(Programmerings)sprog • Linguistik (sproglære) inddeler læren af sprog i: • Syntaks: Hvordan er (velformede) sætninger i sproget bygget op? • Semantik: Hvad betyder sætningerne? • Pragmatik: Hvordan bruges sproget mest hensynsmæssigt? • Tilsvarende for programmeringssprog, f.eks. Java: • Syntaks: Hvad er velformede Java programmer? • Semantik: Hvad sker der, når man udfører et velformet Java program? • Pragmatik: Hvordan bruges sprogets faciliteter bedst muligt for få effektive, let-forståelige, genbrugelige, testbare, modulære programmer?
Type Identifier Parameters Throws clause Modifier void Method body Java syntaks Syntaksen for Java, f.eks. hvordan en metode kan se ud, kan beskrives på forskellig måde. En mulighed er syntaksdiagrammer, som i L&L appendiks L. Metodeerklæringer er beskrevet som: public double indsæt (double beløb) { saldo += beløb; } Syntaksdiagrammer viser hvordan syntaksen er, men ikke hvad det betyder.
void Modifier Java syntaks valgmulighed ved forgreninger slutprik til højre i diagrammet Throws clause En kasse er navnet på et andet syntaksdiagram ovaler angiver et nøgleord, eller en konstant i sproget. startprik til venstre i diagrammet Throws vil vi ikke se på før i lektion 12. Her er det med for at vise at en Throws clause kan bestå af den tomme streng (ved at vælge øverste linje ret gennem diagrammet).
Konto klasse public class Konto { private double saldo; private double maxOvertræk; private String ejer; public Konto(String ejeren) { ejer = ejeren; saldo = 0; maxOvertræk = -3000; } public double hæv(double beløb) { if (saldo-beløb >= maxOvertræk) { saldo = saldo - beløb; return beløb; } else { return 0; } } Hvert objekt lavet ud fra klassen Konto har sin egen saldo, maxOvertræk, og ejer. Når man laver et objekt skal man angive ejeren. Dette angives i konstruktøren. Der er tre metoder, som bruges til at hæve, indsætte, og aflæse saldo. public void indsæt(double beløb) { saldo += beløb; } public double aflæsSaldo() { return saldo; } } forts.
Overførsel af penge Ny metode i Konto klassen. public void overførTil(Konto modtager, double beløb){ if (this.hæv(beløb) == beløb) modtager.indsæt(beløb); }
Konto lønKonto = new Konto(”Kasper”); Konto minKonto = lønKonto; lønKonto.indsæt(3000); int beløb = minKonto.aflæsSaldo(); int huskSaldo = beløb; minKonto.hæv(500); beløb = lønKonto.aflæsSaldo(); Referencer 1) lønKonto Konto saldo: 0 maxOvertræk: ejer: Kasper Variablen lønKonto er en reference til et konto objekt. En reference er en entydig identifikation af et objekt. new operatoren laver et nyt objekt, og konstruktør metoden giver instans variablene deres start værdi.
Referencer 2) lønKonto Konto Konto lønKonto = new Konto(”Kasper”); Konto minKonto = lønKonto; lønKonto.indsæt(3000); int beløb = minKonto.aflæsSaldo(); int huskSaldo = beløb; minKonto.hæv(500); beløb = lønKonto.aflæsSaldo(); saldo: 0 maxOvertræk: ejer: Kasper minKonto Variablen minKonto kan også referere til Konto objekter. Assignmentet får minKonto til at referere det samme objekt som lønKonto variablen. Teknisk siger man at minKonto og lønKonto er aliaser for det samme objekt.
Referencer 3) lønKonto Konto Konto lønKonto = new Konto(”Kasper”); Konto minKonto = lønKonto; lønKonto.indsæt(3000); int beløb = minKonto.aflæsSaldo(); int huskSaldo = beløb; minKonto.hæv(500); beløb = lønKonto.aflæsSaldo(); saldo: 3000 maxOvertræk: ejer: Kasper minKonto beløb 3000 Ved kaldet ”lønKonto.indsæt(3000)” er det metoden på det objekt som lønKonto variablen referere der aktiveres. Derfor er det ligegyldigt om jeg aflæser saldo gennem den ene eller den anden variabel. Aflæsningen sker igen via referencen.
Referencer 4) lønKonto Konto Konto lønKonto = new Konto(”Kasper”); Konto minKonto = lønKonto; lønKonto.indsæt(3000); int beløb = minKonto.aflæsSaldo(); int huskSaldo = beløb; minKonto.hæv(500); beløb = lønKonto.aflæsSaldo(); saldo: 3000 maxOvertræk: ejer: Kasper minKonto beløb huskSaldo 3000 3000 beløb og huskSaldo er begge heltal, ikke objekter. De er derfor ikke alias for hinanden, men to adskilte variable. Egentlig er dette totalt umystisk. Objekt variable gemmer ikke objekter, men objekt referencer. Når man assigner en objekt variabel, så kopieres referencen, på samme måde som heltallet 3000 kopieres fra beløb til huskSaldo.
Referencer 5) lønKonto Konto Konto lønKonto = new Konto(”Kasper”); Konto minKonto = lønKonto; lønKonto.indsæt(3000); int beløb = minKonto.aflæsSaldo(); int huskSaldo = beløb; minKonto.hæv(500); beløb = lønKonto.aflæsSaldo(); saldo: 2500 maxOvertræk: ejer: Kasper minKonto beløb huskSaldo 2500 3000 Beløb og huskSaldo er nu forskellige, idet beløb er ændret, men ikke huskSaldo. Det er stadig ligegyldigt hvilken objekt variabel jeg bruger til at operere på objektet, idet de to variable refererer til samme objekt.
Referencer 6) lønKonto Konto lønKonto = new Konto(”Kasper”); Konto minKonto = lønKonto; lønKonto.indsæt(3000); int beløb = minKonto.aflæsSaldo(); int huskSaldo = beløb; minKonto.hæv(500); beløb = lønKonto.aflæsSaldo(); lønKonto = new Konto(”Østerbye”); Konto saldo: 2500 maxOvertræk: ejer: Kasper minKonto beløb Konto 2500 saldo: 0 maxOvertræk: ejer: Østerbye huskSaldo 3000 Der er lavet et nyt objekt, og lønKonto variablen refererer til det nye objekt. minKonto refererer stadig til det gamle.
modtager Referencer 7) Konto minKonto = new Konto(”Kasper”); Konto dinKonto = new Konto(”Dilbert”); ... minKonto.overførTil(dinKonto,1205); dinKonto Konto saldo: 2500 maxOvertræk: ejer: Dilbert public void overførTil (Konto modtager, double beløb) { if (this.hæv(beløb) == beløb) modtager.indsæt(beløb); } minKonto Konto saldo: 0 maxOvertræk: ejer: Kasper Under aktiveringen af ”overførTil” er ”modtager” et alias for Dilberts konto. this er en reference til det objekt som i øjeblikket har fået denne metode aktiveret. Altså this refererer Kaspers konto objekt
Man kan i særlige tilfælde få brug for tilstand der ikke er knyttet til et specifikt objekt, men er fælles for en række objekter. F.eks. alle konto objekter skal have et konto nummer som er et løbenummer. Man kan i Java knytte metoder og variable til klassen i stedet for til et objekt. Man kalder den slags klassemetoder og klassevariable. Af historiske grunde (fordi Java er inspireret af C og C++), kaldes klassemetoder og -variable også for statiske metoder og variable. Man angiver om en metode eller variabel er en klassevariabel ved at skrive static foran metoden eller variablen. Static
En instansmetode tilhører et bestemt objekt. En instansmetode kan kun tilgås fra et objekt (angives før ”.”). En instansmetode kan bruge og opdatere alle instansvariable. En instansmetode kan bruge og opdatere alle klassevariable. En instansmetode kan referere til this (modtagerobjektet for metoden) En instansmetode kan først invokeres når der er dannet et objekt. En klassemetode tilhører klassen, ikke noget bestemt objekt. En klassemetode kan kun tilgås fra en klasse (klassenavn angives før ”.”) En klassemetode kan ikke tilgå instansvariable. En klassemetode kan bruge og opdatere alle klassevariable. En klassemetode kan ikke referere til this. En klassemetode kan invokeres uden at der er dannet et objekt. Instansmetoder og klassemetoder
public class Konto { private double saldo; private double maxOvertræk; private String ejer; private int kontoNummer; private static int løbeNummer = 1; public Konto(String ejeren) { ejer = ejeren; saldo = 0; maxOvertræk = -3000; kontoNummer = løbeNummer; løbeNummer = løbeNummer +1; } .... } Løbenumre i Konto static angiver at det er en klasse variabel. private at den ikke kan ses ude fra. variablen løbenummer får sin værdi når klassen bliver lavet, hvilket er første gang klassen bliver brugt. Man kan aflæse klasse variable som enhver anden variabel Og den kan også tildeles en ny værdi. Resultatet er at enhver konto objekt får sit eget konto nummer.
public static int max(int a, int b) { int resultat; if (a>b) resultat = a; else resultat = b; return resultat; } .... public static void main(String[] args){ System.out.println( max(5,9) ); System.out.println( max(-5,-9) ); System.out.println( max(5,5) ); } Metoder (review) Dette kaldes metodens hoved. Her angives navn og type på hver parameter. metodens navn er max, og typen af det den giver som resultat står umiddelbart før navnet (her int). Hvis metoden ikke returnerer noget, angiver man det med void. I forbindelse med en aktivering af max, vil a og b få tildelt værdier – f.eks. 5 og 9. Når der i hovedet er angivet en retur type (ikke void), skal der være en return. Den behøver dog ikke at stå til sidst. a og b kaldes formelle parametre, mens de værdier der gives med ved aktivering kaldes aktuelle parametre, eller argumenter.
Metodeaktiveringer og kaldsstakken public class Konto { private double saldo; private double maxOvertræk; private String ejer; public Konto(String ejeren) { ejer = ejeren; saldo = 0; maxOvertræk = -3000; } public double hæv(double beløb) { if (saldo-beløb >= maxOvertræk) { saldo = saldo - beløb; return beløb; } else { return 0; } } public void indsæt(double beløb) { saldo += beløb; } public double aflæsSaldo() { return saldo; } public void overførTil (Konto modtager, double beløb){ if (this.hæv(beløb) == beløb) modtager.indsæt(beløb); } } forts. Givet denne konto klasse, vil vi følge aktiveringen af overførTil neden for. Konto minKonto = new Konto(”Kasper”); Konto dinKonto = new Konto(”Dilbert”); ... minKonto.overførTil(dinKonto,1205);
En metodeaktivering • En metode aktivering indeholder følgende 3 ting. • For det første indeholder den lokale variable og parametre for denne aktivering af metoden. • For det andet indeholder den en reference til hvilket objekt denne metode er aktiveret på – this objektet. • og endelig indeholder den det sted i programmet hvor vi skal vende tilbage til når metoden er færdig.
saldo: 1500 maxOvertræk: -3000 ejer: ”Kasper” modtager: beløb: 1205 saldo: 2000 maxOvertræk: -3000 ejer: ”Dilbert” this: retur til: ??? Aktiveringen af overførTil public void overførTil (Konto modtager, double beløb){ if (this.hæv(beløb) == beløb) modtager.indsæt(beløb); }
I debuggeren I if sætningen aktiveres hæv metoden
saldo: 1500 maxOvertræk: -3000 ejer: ”Kasper” modtager: beløb: 1205 saldo: 2000 maxOvertræk: -3000 ejer: ”Dilbert” this: retur til: ??? Aktiveringen af hæv public double hæv(double beløb) { if (saldo-beløb >= maxOvertræk) { saldo = saldo - beløb; return beløb; } else { return 0; } } saldo betegner i denne aktivering saldoen i Kaspers konto, idet this er Kaspers konto. beløb: 1205 this: retur til: ???
I debuggeren Vi returnerer fra denne aktivering
saldo: 295 maxOvertræk: -3000 ejer: ”Kasper” modtager: beløb: 1205 saldo: 2000 maxOvertræk: -3000 ejer: ”Dilbert” this: retur til: ??? Aktiveringen af overførTil public void overførTil (Konto modtager, double beløb){ if (this.hæv(beløb) == beløb) modtager.indsæt(beløb); } Vi er nu kommet tilbage fra hæv, men har endnu ikke indsat beløbet på Dilberts konto.
I debuggeren Vi aktiverer metoden indsæt
saldo: 1500 maxOvertræk: -3000 ejer: ”Kasper” modtager: beløb: 1205 saldo: 2000 maxOvertræk: -3000 ejer: ”Dilbert” this: retur til: ??? Aktiveringen af indsæt public void indsæt(double beløb) { saldo += beløb; } saldo betegner i denne aktivering saldoen i Dilberts konto, idet this er Dilberts konto, fordi vi kaldte metoden som ”modtager.indsæt(beløb)” beløb: 1205 this: retur til: ???
I debuggeren Vi returnerer fra denne aktivering
saldo: 295 maxOvertræk: -3000 ejer: ”Kasper” modtager: beløb: 1205 saldo: 3205 maxOvertræk: -3000 ejer: ”Dilbert” this: retur til: ??? Aktiveringen af overførTil public void overførTil (Konto modtager, double beløb){ if (this.hæv(beløb) == beløb) modtager.indsæt(beløb); } Vi er nu kommet tilbage fra indsæt og er færdige.