Föreläsning 7-8 Innehåll Objekt som argument Antag att vi har lagt till följande metod i klassen Square (från lab 4). Mer om att skriva egna klasser Fel och felsökning Klasserna String och StringBuilder /** Returnerar true om kvadraten har större area än kvadraten other, i annat fall returneras false. */ public boolean biggerthan(square other) { return side > other.side; Förklaring: side > other.side är ett logiskt uttryck som får värdet true eller false beroende på utfallet av jämförelsen. Det är detta värde som returneras. Vi behöver inte beräkna areorna, det räcker med att jämföra sidlängderna. Men detta fungerar också: public boolean biggerthan(square other) { return getarea() > other.getarea(); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 1 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 2 / 42 Anropa metod på objektet självt Hur komma åt den andra kvadratens attribut? Isatsen return getarea() > other.getarea(); beräknas den aktuella kvadratens area genom anropet getarea(). Normalt anger man med punktnotation vilket objekt en metod ska utföras på. Det behövs inte i det här fallet. Metoden getarea är deklarerad i klassen Square och utförs på det aktuella objektet. Man kan också anropa metoden så här: return this.getarea() > other.getarea(); this är en referens till objektet själv. Den aktuella kvadratens sidlängd når vi som vanligt via attributet side. Genom att anropa metoden getside på other får vi den andra kvadratens sidlängd: return side > other.getside(); Men i det här specialfallet, när även parametern har typen Square, kan vi nå det andra objektets attribut direkt: return side > other.side; Detta beror på att attributen är privata för klassen, inte för ett specifikt objekt. Datavetenskap (LTH) Föreläsning 7-8 HT 2017 3 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 4 / 42
Scope Scope Med en scope menas den del av ett program där en identifierare (attribut, variabel, parameter, metod etc) får användas. En identifierare får användas i det block (satser som omges av { ) den är deklarerad. Exempel: public class Square { private int x; private int y; private int side; public void move(int dx, int dy) { // Här får man använda attributen x, y, side // och parametrarna dx, dy Diskutera Ett program kan ses som en modell av verkligheten. Är det här programmet (som beräknar antal kast som krävs för att få en 6:a) en bra modell? public class NbrRolls { public static void main(string[] args) { Random rand = new Random(); int n = rand.nextint(6) + 1; int nbrrolls = 1; while (n!= 6) { n = rand.nextint(6) + 1; nbrrolls++; System.out.println("Det krävdes " + nbrrolls + " kast."); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 5 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 6 / 42 Klass som beskriver en tärning? Ny version av kasta tärning-programmet För att kasta tärningen gör vi så här: int n = rand.nextint(6) + 1; Lätt att glömma bort att addera med 1. Svårläst. Lösning: skriv en tärningsklass där allt med slumptal göms undan: /** Skapar en tärning. */ Die(); /** Kastar tärningen. */ void roll(); /** Tar reda på resultatet av det senaste kastet. */ int getdots(); public class NbrRolls { public static void main(string[] args) { Die d = new Die(); d.roll(); int nbrrolls = 1; while (d.getdots()!= 6) { d.roll(); nbrrolls++; System.out.println("Det krävdes " + nbrrolls + " kast."); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 7 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 8 / 42
Klassen Die public class Die { private Random rand; private int dots; // slumptalsgenerator // antal prickar som visas /** Skapar en tärning. */ public Die() { rand = new Random(); roll(); // så att dots får ett värde 1..6 /** Kastar tärningen. */ public void roll() { dots = rand.nextint(6) + 1; /** Tar reda på resultatet av det senaste kastet. */ public int getdots() { return dots; Datavetenskap (LTH) Föreläsning 7-8 HT 2017 9 / 42 Diskutera Ändra i tärningsklassen så att vi kan ha annat än 6-sidiga tärningar. Behövs det fler attribut? Behöver konstruktorn ändras? Behöver någon av de övriga metoderna ändras? Klassen Die Alternativ med default-konstruktor public class Die { private Random rand new Random(); // slumptalsgenerator private int dots = 1; // antal prickar som visas /** Kastar tärningen. */ public void roll() { dots = rand.nextint(6) + 1; /** Tar reda på resultatet av det senaste kastet. */ public int getdots() { return dots; Vi har inte skrivit någon konstruktor. Klassen får då en default -konstruktor: public Die () { Datavetenskap (LTH) Föreläsning 7-8 HT 2017 10 / 42 Klassen Die Variant med olika antal sidor public class Die { private Random rand; private int dots; private int sides; /** Skapar en 6-sidig tärning. */ public Die() { sides = 6; rand = new Random(); roll(); // slumptalsgenerator // antal prickar som visas // antal sidor /** Skapar en tärning med sides sidor. */ public Die(int sides) { this.sides = sides; rand = new Random(); roll(); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 11 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 12 / 42
Klassen Die Variant med olika antal sidor elegantare lösning Klassen Die, forts Variant med olika antal sidor public class Die { private Random rand; private int dots; private int sides; // slumptalsgenerator // antal prickar som visas // antal sidor Anropet av nextint i metoden roll måste ändras. Attributet dots ska få ett värde mellan 1 och antal sidor. /** Skapar en 6-sidig tärning. */ public Die() { this(6); // anrop av den andra konstruktorn /** Skapar en tärning med sides sidor. */ public Die(int sides) { this.sides = sides; rand = new Random(); roll(); /** Kastar tärningen. */ public void roll() { dots = rand.nextint(sides) + 1; /** Tar reda på resultatet av det senaste kastet. */ public int getdots() { return dots; Datavetenskap (LTH) Föreläsning 7-8 HT 2017 13 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 14 / 42 Överlagring Fel i program ( buggar ) I klassen Die på förra bilden finns två konstruktorer: public Die() { public Die(int sides) { Det kan finnas flera konstruktorer eller flera metoder med samma namn i en klass. Antalet parametrar och/eller parametrarnas typer måste skilja sig åt. Detta kallas överlagring (eng. overloading). Kompileringsfel brytermotspråketsgrammatik(syntax). glömt ett { glömt deklarera en variabel innan den används Exekveringsfel (Runtime errors) upptäcks vid exekvering. ArrayIndexOutOfBoundException NullPointerException Logiska fel Programmet kan köras men ger fel resultat. istället för + oavsiktlig heltalsdivision undersöker bara första elementet vid sökning i en vektor Datavetenskap (LTH) Föreläsning 7-8 HT 2017 15 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 16 / 42
Felsökning Klassen String Klassen String beskriver en teckensträng (en följd av tecken). Tecknen kan läsas av men inte ändras. Några råd: Börja med ett litet program och lägg till funktionalitet efter hand. Provkör ofta. Lägg in utskriftsrader för att se vad som händer programmet. Använd debugger. Exempel: String s = "En massa tecken"; String empty = ""; Kursboken Think Java beskriver detta på ett utmärkt sätt. Se appendix C. s empty En massa tecken Datavetenskap (LTH) Föreläsning 7-8 HT 2017 17 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 18 / 42 Slå ihop (konkatenera) strängar Behandla alla tecken i strängen String s1 = "En text"; String s2 = "En text till"; String result = s1 + " och " + s2; Mönster: String s = ; for (int i = 0; i < s.length(); i++) { // aktuellt tecken nås med anropet s.charat(i); s1 s2 result En text En text till En text och En text till Exempel: Räkna antal blanktecken i strängen s. int spaces = 0; for (int i = 0; i < s.length(); i++) { if (s.charat(i) == ) { spaces++; Datavetenskap (LTH) Föreläsning 7-8 HT 2017 19 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 20 / 42
Diskutera Jämföra teckensträngar med equals Vad skrivs ut? Förklara varför. Scanner scan = new Scanner(System.in); String s1 = scan.next(); String s2 = scan.next(); if (s1 == s2) { System.out.println("Lika"); else { System.out.println("Inte lika"); s1 s2 abc abc Vill man jämföra innehållet i teckensträngarna måste man använda metoden equals: /** Returnerar true om innehållet i aktuell sträng är lika med innehållet i s. */ boolean equals(object s); Exempel: if (s1.equals(s2)) { System.out.println("Samma innehåll"); else { System.out.println("Inte samma innehåll"); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 21 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 22 / 42 Jämföra teckensträngar med compareto Metoden tostring Med metoden compareto kan man avgöra om en sträng är större än eller mindre än en annan sträng: /** Jämför aktuell sträng med s. Returnerar 0 om teckensträngarna är lika, ett negativt tal om aktuell sträng är mindre än s, ett positivt tal om aktuell sträng är större än s. */ int compareto(string s); Exempel: String s1 = "java"; s1.compareto("java") == 0 s1.compareto("javac") < 0 s1.compareto("java") > 0 s1.compareto("jazz") < 0 Det är vanligt att man lägger till metoden tostring i sina klasser. Metoden tostring anropas t.ex. inuti println och används av debuggern när ett objekt ska skrivas ut. Metoden tostring skulle t.ex. kunna se ut så här i klassen Square: public String tostring() { return x + " " + y + " " + side; eller så här: public String tostring() { return "Kvadraten har sidlängden " + side + " och övre vänstra hörnet i " + x + "," + y +"."; Datavetenskap (LTH) Föreläsning 7-8 HT 2017 23 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 24 / 42
Teckensträngar kan inte ändras Klassen StringBuilder Teckensträngar kan inte ändras efter det att de skapats. De är oföränderliga (eng. immutable). Lägg märke till att metodanrop som s.tolowercase() eller s.uppercase() inte ändrar strängen s utan istället returnerar en ny sträng. b Klassen StringBuilder beskriver en följd av tecken som kan läsas och ändras. Exempel: StringBuilder b = new StringBuilder("En massa tecken"); b.append("!"); En massa tecken! Datavetenskap (LTH) Föreläsning 7-8 HT 2017 25 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 26 / 42 Några metoder i klassen StringBuilder /** Skapar en tom strängbuffert. */ StringBuilder(); /** Skapar en strängbuffert med samma innehåll som s. */ StringBuilder(String s); /** Tar reda på antal tecken. */ int length(); /** Tar reda på tecknet på plats pos. */ char charat(int pos); /** Returnerar ett String-objekt med samma innehåll som denna strängbuffert. */ String tostring(); Ändra innehållet i StringBuilder-objekt /** Lägger in s efter tecknen i strängbufferten. */ StringBuilder append(string s); /** Ändrar tecknet på plats k till ch. */ void setcharat(int k, char ch); /** Lägger in s på plats k, flyttar tecknen efter. */ StringBuilder insert(int k, String s); /** Tar bort tecknet på plats k. */ StringBuilder deletecharat(int k); Man kan sätta in värden av andra typer än String i ett StringBuilderobjekt. Det finns flera överlagrade metoder append och insert. Dessa har en parameter av typen int, double, char,. Datavetenskap (LTH) Föreläsning 7-8 HT 2017 27 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 28 / 42
Exempel När man ska sätta ihop många delar till en sträng kan det vara praktiskt att använda ett StringBuilder-objekt och metoden append. Man kan alternativt slå ihop delsträngar med +, men det kan vara ineffektivt (= ta längre tid) ifall det är många delar. /** Returnerar en sträng innehållande elementen i vektorn a med kommatecken mellan. */ public static String tostring(int[] a) { StringBuilder b = new StringBuilder(); for (int i = 0; i < a.length; i++) { if (i > 0) { b.append(, ); b.append(a[i]); return b.tostring(); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 29 / 42 Förskjutningschiffer I förskjutningschiffer (ceasarchiffer) byter man ut varje bokstav mot bokstaven ett bestämt antal steg framåt i alfabetet. Exempel: om antal steg (chiffernyckeln) är 3 byts A ut mot D osv: ABCDEFGHIJKLMNOPQRSTUVWXYZ DEFGHIJKLMNOPQRSTUVWXYZABC Exempel: JAVA -> MDYD När man dekrypterar texten gör man samma sak i motsatt riktning. Exempel: MDYD -> JAVA Datavetenskap (LTH) Föreläsning 7-8 HT 2017 30 / 42 Rot13 Kryptera ett tecken I chiffret Rot13 används chiffernyckeln 13. Rot13 är sin egen invers, dvs. man kan kan använda samma algoritm för att kryptera och dekryptera. ABCDEFGHIJKLMNOPQRSTUVWXYZ NOPQRSTUVWXYZABCDEFGHIJKLM Exempel: JAVA -> WNIN -> JAVA Vi ska skriva ett program som läser en text och krypterar alla tecken i intervallet [A-Za-z] med chiffret Rot13. Börja med det enklare delproblemet att kryptera ett tecken i intervallet [A-Za-z]: ABCDEFGHIJKLMNOPQRSTUVWXYZ NOPQRSTUVWXYZABCDEFGHIJKLM Detta kan man lösa genom följande algoritm: om tecknet är i intervallet [A-Ma-m] ersätt tecknet med bokstaven 13 steg framåt i alfabetet annars om tecknet är i intervallet [N-Zn-z] ersätt tecknet med bokstaven 13 steg bakåt i alfabetet Datavetenskap (LTH) Föreläsning 7-8 HT 2017 31 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 32 / 42
Tecken Konvertering mellan tecken och heltal Exempel: char c1 = A ; char c2 = 7 char space = ; Observera att det ska vara apostrofer omkring en teckenkonstant. Tecknen är internt numrerade 0, 1, 2, enligt Unicode-tabellen: Siffrorna 0 till 9 kommer i följd (nr 48-57). Bokstäverna A till Z kommer i följd (nr 65-90). Bokstäverna a till z kommer i följd (nr 97-122) Å, Ä, Ö och å, ä, ö är besvärliga att hantera. De kommer inte direkt efter de andra bokstäverna och dessutom i fel ordning. Ett tecken i ett heltalsuttryck konverteras automatiskt till motsvarande heltal. char c = D ; int nr = c + 13; // 68 + 13 I andra riktningen måste man konvertera explicit. c = (char) nr; c nr c nr 'D' 81 'Q' 81 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 34 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 33 / 42 Metod för att kryptera ett tecken Läsa och kryptera ett tecken public class Encrypter { Skriv ett program som läser ett tecken och chiffrerar det. /** Krypterar ett tecken i intervallet [A-Za-z] genom att använda krypteringsalgoritmen Rot13. */ public static char encryptrot13(char c) { if (c >= a && c <= m c >= A && c <= M ) { c = (char)(c + 13); else if (c >= n && c <= z c >= N && c <= Z ) { c = (char)(c - 13); return c; public class Rot13 public static void main(string[] args) { Scanner scan = new Scanner(System.in); String s = scan.next(); char c = s.charat(0); scan.close(); c = Encrypter.encryptRot13(c); System.out.print(c); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 35 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 36 / 42
Inläsning av ett tecken Läsa och kryptera en teckensträng I klassen Scanner finns en metod next för att läsa in en teckensträng: String name = scan.next(); Det finns ingen speciell metod för att läsa in ett värde av typen char. Istället kan man t.ex. läsa en teckensträng metoden next och sedan plocka ut första tecknet. Scanner scan = new Scanner(System.in); String name = scan.next(); char initial = name.charat(0); Skriv ett program som läser en teckensträng och chiffrerar den. Algoritm: läs en teckensträng för varje tecken i teckensträngen kryptera tecknet skriv ut Datavetenskap (LTH) Föreläsning 7-8 HT 2017 37 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 38 / 42 Läsa och kryptera en teckensträng, forts Läsa och kryptera en text Skriv ett program som läser en teckensträng och chiffrerar den. public class Rot13 public static void main(string[] args) { Scanner scan = new Scanner(System.in); String s = scan.next(); scan.close(); for (int i = 0; i < s.length(); i++) { char c = s.charat(i); c = Encrypter.encryptRot13(c); System.out.print(c); Skriv ett program som läser en text och chiffrerar den. Algoritm: Så länge det finns en rad att läsa läs en rad för varje tecken på raden kryptera tecknet skriv ut Datavetenskap (LTH) Föreläsning 7-8 HT 2017 39 / 42 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 40 / 42
Programexempel: Rot13 Läsa och kryptera en text, forts Checklista Skriv ett program som läser en text och chiffrerar den. public class Rot13 public static void main(string[] args) { System.out.println("Skriv texten som ska krypteras:"); Scanner scan = new Scanner(System.in); while (scan.hasnextline()) { String s = scan.nextline(); for (int i = 0; i < s.length(); i++) { char c = s.charat(i); c = Encrypter.encryptRot13(c); System.out.print(c); System.out.println(); scan.close(); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 41 / 42 Exempel på vad du ska kunna Implementera egna klasser. Förklara begreppet scope och veta var i programmet man kan använda en identifierare (variabel, attribut, parameter, metod ). Förklara begreppen kompileringsfel, exekveringsfel och logiskt fel. Felsöka i program, bland annat med hjälp av debugger. Använda klasserna String och StringBuilder Datavetenskap (LTH) Föreläsning 7-8 HT 2017 42 / 42