Typer Objektorienterad programmering E Typkonvertering Typkonvertering Satser: while, for, if Objekt Föreläsning 2 Implicit konvertering Antag att vi i ett program deklarerat int n=3; double x = 5.2; Då gäller följande: Uttryck Typ Värde n/4 int n/4. double.75 5+n/4 > x boolean false Tilldelning och konvertering Med samma deklarationer har vi att double y = n; double z = n/4; är typkorrekta. y får värdet 4. och z värdet.. Följande ger däremot typfel: int k = x; int m = n/4.; Bakomliggande princip Implicit konvertering får inte göras om man kan förlora information! Typer Explicit typkonvertering int n = (int)(6 * Math.random()); Math.random() ger ett slumpmässigt tal mellan och 1 (kan vara men inte 1) av typ double. Alltså är 6 * Math.random() ett double-värde mellan och 6. Typkonverteringen (int)... konverterar detta till ett heltal genom att avrunda nedåt. Resultatet blir ett slumpmässigt heltal mellan och 5 (inklusive). Utan typkonvertering skulle vi få typfel. Typer Java versus C HarmonicSum i C #include <stdio.h> double hsum(int n) { double sum = ; int i; for (i=1; i<=n; i++) sum = sum + 1./i; return sum; int main(int argc, char** argv) { int n; sscanf(argv[1],"%d",&n); printf("summan med %d termer ", n); printf("blir %f\n", hsum(n));
Satser: while-satsen Syntaxbeskrivning while (expression) { Typvillkor expression måste ha typ boolean. Effekt while-satsen exekveras på följande sätt: 1 expression beräknas. 2 Om resultatet blir false, avslutas exekveringen av satsen. Om resultatet blir true, exekveras och därefter börjar man om med 1). : kvadratrötter Beräkning av a. Låt x = 1 och beräkna xn+1 = (xn + a/xn)/2, n = 1, 2,... tills skillnaden mellan två successiva xn blir högst ε. Uppgift Definiera en funktion public static double sqrt(double a) som implementerar denna algoritm. Välj ε = 1 1 Lösning Kodat i Java public static double sqrt(double a) { final double eps = 1e-1; double oldx = 1; double newx = (1+a)/2; while (Math.abs(oldx-newx) > eps) { oldx = newx; newx = (oldx + a/newx)/2; return newx; Variabler med modifierare final En variabel som deklarerats att vara final kan bara tilldelas ett värde en gång. Kan hjälpa till att hitta fel och kan ge bättre kod. for-satsen Syntax-beskrivning: for-statement for(initialization; continuation-condition; update) { Typvillkor Typen av continuation-condition måste vara boolean. Effekt for-satsen är likvärdig med initialization while (continuation-condition) { update
sqrt och klassen Math if-satsen, form 1 (utan else) Många av matematikens vanliga funktioner finns i standardklassen Math; klassnamnet måste anges vid användning: Math.sqrt(2.5). Ni måste lära er att hitta funktioner i Java 1.6 API (Application Programming Interface. Här beskrivs alla biblioteksklasser och deras metoder. En länk finns på kursens webbplats. Uppgift Skriv ett program som tar ett positivt heltal n som kommandoradsargument och skriver ut alla primtal mindre än n. Syntaxbeskrivning if (expression) { Typvillkor Typen av expression måste vara boolean. Effekt Satsen exekveras på följande sätt: Exekvera expression. Om resultatet blir true, exekvera, annars avsluta satsen. Andra former av if Tvåvägs if (expression) { else { Flervägs if (expression) { else if (expression) { else { Collatz problem Formulering För ett givet positivt heltal N, bilda en talföljd a, a1, a2,... på följande sätt. a = N odefinierat om ak = 1. ak+1 = 3 ak + 1 om ak är udda och skilt från 1. ak/2 om ak är jämnt. Kommer talföljden att för alla N komma till 1 och sluta? N = 15. Följden blir 15, 46, 23, 7, 35, 16, 53, 16, 8, 4, 2, 1, 5, 16, 8, 4, 2, 1
Funktioner och subrutiner Funktioner En funktion har formen modifiers return-type name (parameters) { Varje gren av exekvering måste avslutas med en sats return expression; En subrutin har formen modifiers void name (parameters) { En gren av exekvering får avslutas med satsen return; Lokala variabler, parametrar och returvärde Lokala variabler En variabel som deklareras i en subrutin kan bara användas där; den är lokal. Parametrar Parametrarna till en subrutin är lokala variabler, men de får sina startvärden satta när subrutinen anropas; anropets argumentvärden beräknas och kopieras till subrutinens parametrar innan subrutinens kropp exekveras. Returvärde När man under exekvering av en funktions kropp kommer till return expr, beräknas värdet av expr; funktionen avslutas och detta värde returneras. Mer om lokala variabler Mer om parametrar Lokala variabler måste initieras före de används Kompilatorn kontrollerar detta; ibland är den för försiktig, men det är oundvikligt. Följande (idiotiska) kod underkänns, trots att y alltid skulle initieras:... double x = 2.5; double y; if (x * Math.sin(x + 1.5) < 1) y = 3; x = 2 * y; Parametrar är read only public class Example { public static void double (int n) { n = 2*n; public static void main(string[] args) { int n = 5; double(n); System.out.println(n); Vad skrivs ut?
Biblioteksklasser Testning Funktionsbibliotek Det är vanligt att samla ett antal funktioner och subrutiner för ett visst tillämpningsområde i en biblioteksklass. : Klassen Math. Klassnamnet bör avspegla tillämningsområdet. En sådan klass innehåller normalt ingen main. Användning Om man i en annan del av programmet vill använda funktioner från klassen LinearAlgebra måste man ange namnen som LinearAlgebra.vectorSum, LinearAlgebra.matrixProduct, osv. Enhetstest Ett funktionsbibliotek som ska användas i flera program måste testas noga. Ett sätt är att inkludera en main som anropar alla funktioner i biblioteket för olika argument, kontrollerar resultaten och skriver ut testinformation. När man senare ändrar något i biblioteket, till exempel för att öka effektiviteten, kör man testet igen. Det är mycket vanligt att förbättringar introducerar nya fel! Systemtest Program består typiskt av många samverkande klasser. Systemtest testar hela systemet; detta underlättas om varje klass för sig är noggrant enhetstestad. (eng. arrays) är referenstyper Vektorer En sekvens av relaterade värden kan lagras i ett fält av variabler med gemensamt namn och indexering för att skilja de olika variablerna åt. Alla variabler i ett fält måste ha samma typ. Typen int[] är ett fält av heltalsvariabler. Typen double[] är ett fält av flyttalsvariabler. Typen String[] är ett fält av strängvariabler. Deklaration int[] a; deklarerar fältet a av heltalsvariabler. Skapande a = new int[4]; skapar ett nytt fält; elementen heter a[], a[1], a[2] och a[3] och får alla startvärdet. Variabeln a innehåller en referens till fältet. Innan fältet skapats (med new) är innehållet i a odefinierat och försök att använda a[] osv ger exekveringsfel. int[] a; a a = new int[4]; a a[] a[1] a[2] a[3]
Mer om fält Ofta görs deklaration och skapande samtidigt: int[] a = new a[4]; Elementens startvärden är för numeriska typer, false för boolean och null för referenstyper. Index börjar alltid med. Antalet element ges av a.length. Sista elementet i fältet a är alltid a[a.length-1] Man kan skapa ett fält och initiera med andra startvärden: int[] dayspermonth = {31,28,31,3,31,3,31,31,3,31,3,31; Antalet dagar i januari är dayspermonth[] (!). som parameter Skriv en funktion arraysum med signaturen public static int arraysum(int[] a) När man skriver funktionen antar man att fältet är skapat. Nedan skriver vi inte ut public static. Flera parametrar Skriv en funktion scalarproduct med signaturen double scalarproduct(double[] a, double[] b) När man skriver funktionen antar man att fälten är lika långa. som resultat Skriv en funktion vectorsum med signaturen double[] vectorsum(double[] a, double[] b) som parametrar och resultat Objekt Objekt som parametrar När ett fält är parameter är det referensen som kopieras till parametern. Konsekvenser: Själva fältet med alla data kopieras inte; det skulle bli ineffektivt för stora fält. Om subrutinen tilldelar till en variabel i fältet, så får det effekt för anroparen! som funktionsresultat En funktion som returnerar ett fält returnerar en referens. Konsekvenser: et måste skapas (och fyllas med resultat) i subrutinen. Anroparen ska inte skapa något fält: double[] c = LinearAlgebra.vectorSum(a,b); är objekt Ett fält är ett objekt. Objekt i Java karakteriseras av att variabler av objekttyp innehåller en referens (eller pekare) till objektet, och inte objektet själv. Värden av primitiva typer är inte objekt; variabler innehåller själva värdet. En variabel av referenstyp kan innehålla det speciella värdet null. Ett objekt som ingen variabel längre pekar på återvinns av skräpsamlaren. Andra objekt Den viktigaste användningen av klasser är inte som funktionsbibliotek, utan som mallar att skapa objekt från.