Programmeringsteknik I Föreläsning 3: Klasser och arrayer
Lektion 5 / OU2 Introduktion till klasser som består (och använder sig) av objekt av andra klasser. (Komposition) Vanligaste missförstånden: Kopiera koden från Dice till PairOfDice istället för att använda den existerande klassen Dice. Om man har en metod roll i klassen Dice får man inte ha en metod roll i PairOfDice. Skillnad mellan instansvariabler, parameterar och lokala variabler.
Multipla objekt och värden (1/2) Hur representerar vi flera värden eller objekt av samma typ? Ett sätt: Turtle t1; Turtle t2; Turtle tn; Referera till den Turtle-variabel som motsvarar Turtle i: t4.move(20);
Multipla objekt och värden (2/2) Om vi har en variabel n och vill dynamiskt göra någonting med Turtle # n blir vi tvugna att göra någonting i den här stilen: if(n == 1) t1.move(20); else if(n == 2) t2.move(20); Inte speciellt trevligt eller skalbart. Enbart mycket små program och datamängder kan skrivas så här.
Det vi egentligen vill ha En lista med objekt eller värden Typ: double Typ: Turtle Värde: 2.0 1.0 8.0 3.5 55.2-99.9 Index: 0 1 2 3 4 5 Värde: null null Index: 0 1 2 3 4 5
En lista som kan indexeras effektivt Typ: double Värde: 2.0 1.0 8.0 3.5 55.2-99.9 Index: 0 1 2 3 4 5 System.out.println( + list[2]); Ska ge utskriften: 8.0 double x = list[2] + list[3]; // x får värdet 11.5
Array Arrayer är listor av värden eller objekt som kan indexeras effektivt: a[index] = ; // tilldela ett nytt värde till element index = a[index]; // läs värdet på element index De kan ändra värde, till skillnad från strängar (String) som också är en lista, specifikt med tecken. (Oföränderliga)
Arrayer: Primitiva typer vs Objekttyper Primitiva typer lagras direkt i en sekvens i minnet. Objekttyper lagras utspritt i minnet och arrayen innehåller referenser till objekten precis som tidigare. Typ: double Värde: 2.0 1.0 8.0 3.5 55.2-99.9 Index: 0 1 2 3 4 5 Typ: Turtle Värde: null null Index: 0 1 2 3 4 5
Arrayer Arrayer är objekt: double[] a = a är en referens till ett array-objekt. Arrayer har utöver de lagrade värdena, instansvariabler och metoder. a.length ger arrayens längd. Arrayer har en tostring-metod som är oanvändbar, ett alternativ är: java.util.arrays.tostring(a).
Mer om arrayer Arrayer kan inte ändra storlek. De skapas med en viss storlek N och har så många värden/index (0..N-1). Om man vill förlänga en array, skapa en ny längre array, kopiera över de gamla värdena till den nya arrayen, glöm den gamla arrayen: double[] na = new double[a.length*2]; for(int i = 0; i < a.length; ++i) { na[i] = a[i]; } a = na;
Multipla returvärden I PairOfDice-uppgiften fanns en deluppgift att skriva en eller flera metoder som returnerar det aktuella värdet på tärningarna. Utan arrayer krävs två metoder getvalue1() och getvalue2() eftersom multipla returvärden inte finns i Java. Med arrayer kan dock multipla värden (av samma typ!) returneras: public int[] getvalues() { int[] result = new int[]{d1.getvalue(), d2.getvalue()}; return result; }
For-loopen, en arrays bästa vän Ett vanligt sätt att iterera över elementen i en array är for-loopen här för att summera: double s = 0.0; for(int i = 0; i < a.length; ++i) { s += a[i]; } Vi indexerar fram till men inte med a.length. Om vi skriver i <= a.length då går vi för långt och får felet: ArrayIndexOutOfBoundsException.
For-loopen - Syntax For-loopen har följande struktur: for(init; Cond; Incr) {} Init: deklarerar variabler som finns enbart inuti loopen, och ger dem initiala värden. Cond (villkoret): är ett boolskt uttryck som avgör om en till iteration av loopen ska påbörjas. (Det är möjligt att loopen inte körs alls) Incr: Uppdaterar loop-variablerna efter varje iteration.
For-loopen, och While-loopen double s = 0.0; for(int i = 0; i < a.length; ++i) { s += a[i]; } i finns inte efter loopen Eller: double s = 0.0; int i = 0; While(i < a.length) { s += a[i]; ++i; } i finns efter loopen
For-loopen och While-loopen ekvivalenta Det man kan göra med den ena, kan man göra med den andra. For-loopen är en ergonomisk konstruktion som gör vanliga uppgifter lättare och mer kortfattade. (Syntaktiskt socker) Väldigt få programmeringsspråkskonstruktioner är strikt nödvändiga för maskinen, de flesta är till för oss människor. Man ska inte underskatta funktioner som bara är trevliga.
Några fler vanliga algoritmer: Min (1) int ind = -1; double minval = Double.POSITIVE_INFINITY; for(int i = 0; i < a.length; ++i) { if(a[i] < minval) { } } ind = i; minval = a[i];
Några fler vanliga algoritmer: Min (2) int ind = 0; double minval = a[0]; // Kräver att a.length > 0 for(int i = 1; i < a.length; ++i) { if(a[i] < minval) { } } ind = i; minval = a[i];
Traktrix Istället för: t1.turnto(t2); t2.turnto(t3); så kan vi lagra paddorna i en array och iterera: (vi kan nu lättare ändra antalet paddor) for(int i = 0; i < 4; ++i) { int nextturtle = (i+1) % 4; t[i].turnto(t[nextturtle]); }
Vanliga fel med arrayer Man läser utanför arrayens domän, till exempel: for(int i = 0; i <= a.length; ++i) System.out.println( + a[i]); Man glömmer att initialisera arrayen: double[] a; a[0] = Math.PI; Man glömmer att initialisera objekten i arrayen: Turtle[] ts = new Turtle[8]; ts[0].move(20); ArrayIndexOutOfBoundsException NullPointerException NullPointerException
Vad är en klass i Java? (Informellt) https://pixabay.com/en/baking-cookies-cookie-cutters-dough-487119/ En mall från vilken objekt kan skapas, som definerar egenskaper och operationer. https://pixabay.com/en/moving-boxes-box-package-cardboard-3407663/ Ett paket/modul där funktionalitet kan samlas under ett namn. (Inte att förväxla med package)
En klass kan representera En konkret fysisk enhet: fordon, person, tärning, sköldpadda En mer abstrakt enhet: bankkonto, triangel, ekvation En programmeringsteknisk enhet: Sträng av tecken, Math, Scanner
En klass är en datatyp En klass definerar en definitionsrymd av möjliga värden som objekt av den typen kan anta. Till exempel heltal, vektorer, namn Och sammansättningar av andra datatyper: en klass med en double och en int som instansvariabel har: double x int som definitionsmängd. Med ett antal operationer, som antingen kan utföra beräkningar, eller ändra på objektet, eller både och.
Klassens beståndsdelar A) Instansvariabler B) Konstruktorer C) Objektmetoder D) Klassmetoder E) Klassvariabler F) Main-metod
Instansvariabler, eller attribut Instansvariabler definerar klassens egenskaper. Varje objekt av typen har en egen uppsättning av instansvariablerna. Alla instansvariabler ska vara private i den här kursen, för att åstadkomma inkapsling. Vi gömmer klassens data, så att bara klassens metoder kommer åt den. Varför? Då kan vi som använder klassen programmera mot klassens interface/gränssnitt/metoder och inte bry oss om detaljerna kring hur klassen är implementerad.
Konstruktor En konstruktor skapar objekt. Anropas vid använding av new ClassName(). Konstruktorn heter samma sak som klassen Den har ingen returtyp: public Dice(int nsides) { } Den är i stort sett alltid public.
Konstruktor En konstruktor kan anropa en annan konstruktor i samma klass om det finns fler än en konstruktor: public Dice() { this(6); } public Dice(int nsides) { this.nsides = nsides; roll(); }
Konstruktion av objekt När Dice d = new Dice(6); körs händer följande i tur och ordning: Minne för att lagra Dice-klassens instansvariabler och övrig data reserveras i minnet. Instansvariablerna får sina standardvärden: int får 0, double får 0.0, referenser får null, etc. Konstruktorn körs, och initierar instansvariablerna till korrekta värden utifrån dess parametrar. Konstruktor returnerar en referens till det nyskapade och initialiserade objektet. Den returnerade referensen sparas i objektvariabeln d.
(Objekt-)Metoder Klasser har ett antal definerade operationer, representerade av dess publika metoder. Där instansvariabler alltid är private i den här kursen, kommer metoder praktiskt alltid vara publika/public. Anropas för att utföra en handling, förändra objektet, skriva/rita på skärmen, eller för att hämta information om objektet (t.ex. dess position, färg, namn, etc)
Klassmetoder Hör till klassen, ungefär som i exemplet med Math: Math.cos, Math.min, Math.pow, Math.sin, Math.abs, etc. Inuti klassmetoder finns inte this, eftersom vi inte anropade metoden för ett specifikt objekt. Används för metoder som inte behöver någon mer data än vad som kan ges via parametrarna. Deklareras med static.
Klassvariabler Variabler som delas av hela klassen, och inte tillhör någon instans av klassen. Deklereras som static. Vanligast är detta konstanter, och deklareras som public: public static final double PI = 3.141592653589793. Ibland kan en räknare eller liknande vara en klassvariabel, för att underlätta skrivandet av simuleringar eller annat, men bör ofta undvikas.
Main-metod Startpunkt för Java-program. Varje program börjar sin exekvering från en main-metod i en klass. Vilken main-metod som körs beror på vilken klass som är öppen i DrJava när man trycker run, eller vilken man kör från kommando-prompten. Main-metoden är static, en klassmetod, eftersom det finns ingen instans av den givna klassen innan programmet har börjat köras. Det är bra att skriva en main-metod i de flesta klasser som ger ett kort exempel på hur klassen kan användas.
Mer om klasser Både metoder och instansvariabler kommer man åt via punktnotation: xyz.abc(); // metoden abc anropas för objektet som xyz refererar till. xyz.abc; // instansvariabeln abc hämtas från objektet som xyz refererar till. Xyz.abc(); // klassmetoden abc anropas för klassen Xyz. Xyz.PI; // klassvariabeln PI hämtas från klassen Xyz.
this is it! this är en referens till ett objekt som: Finns tillgängligt inuti konstruktorer och objektmetoder, men inte inuti klassmetoder. Refererar till objektet som skapas (i konstruktorn) eller till objektet som metoden anropades för (objektet före punkten, xyz.abc(): inuti abc, refererar this till samma objekt som xyz). Kan användas för att komma åt en instansvariabel även när en formell parameter har samma namn (skuggar) instansvariabeln.
this is more This kan också användas för att anropa en konstruktor från en annan för att spara på repetition av kod som vi såg i exemplet med Diceklassen. Att undvika kodduplikation är en viktig del av av skriva program som kan utvidgas, underhållas och felkorrigeras utan att inkonsekventa ändringar kan smyga sig in: Om ett stycke kod finns duplicerad på plats A, B, och C i koden, och vi ändrar på den koden men bara på A och B har vi introducerat ett knepigt fel, som kan vara svårt att hitta.
Exempel: QuadPoly Representerar en andragradsekvation. Instansvariablerna beskriver ekvationens koefficienter, i doublevariabler. Kan evalueras (beräknas) för godtyckliga x. Dess rötter kan beräknas (om real-värda). En s.k. värdeklass, kan ej ändra värde efter konstruktion. Varför? Jo för att instansvariablerna är private, och vi har inte definerat någon metod som ändrar på dem. Introducera inte metoder för att ändra på objektets instansvariabler om det inte är nödvändigt.
Exempel: Klassen Vector Representerar en matematisk vektor. Värden kan avläsas, och ändras. Stöder vektoraddition, vektorsubtraktion, skalärprodukt. Snygg omvandling till strängar med tostring. Har multipla konstruktorer, kan initiseras med nollvärden eller med en angiven konstant.
Exempel: Klassen Matrix Representerar en matematisk matris. Modelleras som en array av vektorer, genom att använda den redan definerade vektor-klassen. Eftersom matris-vektor multiplication kan skrivas som ett antal skalärprodukter kan vi återanvända den kod vi redan har för det ändamålet. Skulle också kunna representeras av en multi-dimensionell array (som Java egentligen mest låtsas att stödja). int[][] arr2d = new int[3][4]; Det blir en array av arrayer av int-variabler.
Lektion 9: Measurements I lektion 9 ska ni skapa en klass Measurements som representerar en serie mätvärden. En array ska användas för att lagra dessa mätvärden (typ double) men den ska växa automatiskt vid behov. Hur kan man representera en växande serie givet att arrayer har en fast storlek? Hur hanterar man oanvända värden i arrayen innan de har lagts till? Felhantering: Vad kan gå fel? Vanligaste felet: Arrayen är inte mätserien Iterera inte över hela arrayen.