Föreläsning 7-8 Innehåll Mer om att skriva egna klasser Fel och felsökning Klasserna String och StringBuilder Datavetenskap (LTH) Föreläsning 7-8 HT 2017 1 / 42
Objekt som argument Antag att vi har lagt till följande metod i klassen Square (från lab 4). /** 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 2 / 42
Anropa metod på objektet självt I satsen 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. Datavetenskap (LTH) Föreläsning 7-8 HT 2017 3 / 42
Hur komma åt den andra kvadratens attribut? 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 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... Datavetenskap (LTH) Föreläsning 7-8 HT 2017 5 / 42
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 6 / 42
Klass som beskriver en tärning? 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(); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 7 / 42
Ny version av kasta tärning-programmet 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 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
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
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? Datavetenskap (LTH) Föreläsning 7-8 HT 2017 11 / 42
Klassen Die Variant med olika antal sidor public class Die { private Random rand; private int dots; private int sides; // slumptalsgenerator // antal prickar som visas // antal sidor /** Skapar en 6-sidig tärning. */ public Die() { sides = 6; rand = new Random(); roll(); /** 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 12 / 42
Klassen Die Variant med olika antal sidor elegantare lösning public class Die { private Random rand; private int dots; private int sides; // slumptalsgenerator // antal prickar som visas // 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();... Datavetenskap (LTH) Föreläsning 7-8 HT 2017 13 / 42
Klassen Die, forts Variant med olika antal sidor Anropet av nextint i metoden roll måste ändras. Attributet dots ska få ett värde mellan 1 och antal sidor.... /** 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 14 / 42
Överlagring 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). Datavetenskap (LTH) Föreläsning 7-8 HT 2017 15 / 42
Fel i program ( buggar ) Kompileringsfel bryter mot språkets grammatik (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 16 / 42
Felsökning 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. Kursboken Think Java beskriver detta på ett utmärkt sätt. Se appendix C. Datavetenskap (LTH) Föreläsning 7-8 HT 2017 17 / 42
Klassen String Klassen String beskriver en teckensträng (en följd av tecken). Tecknen kan läsas av men inte ändras. Exempel: String s = "En massa tecken"; String empty = ""; s empty En massa tecken Datavetenskap (LTH) Föreläsning 7-8 HT 2017 18 / 42
Slå ihop (konkatenera) strängar String s1 = "En text"; String s2 = "En text till"; String result = s1 + " och " + s2; En text En text till s1 s2 result En text och En text till Datavetenskap (LTH) Föreläsning 7-8 HT 2017 19 / 42
Behandla alla tecken i strängen Mönster: String s =...; for (int i = 0; i < s.length(); i++) { // aktuellt tecken nås med anropet s.charat(i); 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 20 / 42
Diskutera 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"); abc s1 s2 abc Datavetenskap (LTH) Föreläsning 7-8 HT 2017 21 / 42
Jämföra teckensträngar med equals 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 22 / 42
Jämföra teckensträngar med compareto 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 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 23 / 42
Metoden tostring 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 24 / 42
Teckensträngar kan inte ändras 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. Datavetenskap (LTH) Föreläsning 7-8 HT 2017 25 / 42
Klassen StringBuilder Klassen StringBuilder beskriver en följd av tecken som kan läsas och ändras. Exempel: StringBuilder b = new StringBuilder("En massa tecken"); b.append("!"); b En massa tecken! 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(); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 27 / 42
Ä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 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
Programexempel: chiffer 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
Programexempel: chiffer Rot13 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. Datavetenskap (LTH) Föreläsning 7-8 HT 2017 31 / 42
Programexempel: chiffer Kryptera ett tecken 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 32 / 42
Tecken 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. Datavetenskap (LTH) Föreläsning 7-8 HT 2017 33 / 42
Konvertering mellan tecken och heltal Ett tecken i ett heltalsuttryck konverteras automatiskt till motsvarande heltal. char c = D ; int nr = c + 13; // 68 + 13 c nr I andra riktningen måste man konvertera explicit. 'D' 81 c = (char) nr; c nr 'Q' 81 Datavetenskap (LTH) Föreläsning 7-8 HT 2017 34 / 42
Programexempel: chiffer Metod för att kryptera ett tecken public class Encrypter { /** 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; Datavetenskap (LTH) Föreläsning 7-8 HT 2017 35 / 42
Programexempel: chiffer Läsa och kryptera ett tecken Skriv ett program som läser ett tecken och chiffrerar det. 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 36 / 42
Inläsning av ett tecken 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); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 37 / 42
Programexempel: chiffer Läsa och kryptera en teckensträng 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 38 / 42
Programexempel: chiffer Läsa och kryptera en teckensträng, forts 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); Datavetenskap (LTH) Föreläsning 7-8 HT 2017 39 / 42
Programexempel: chiffer Läsa och kryptera en text 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 40 / 42
Programexempel: Rot13 Läsa och kryptera en text, forts 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
Checklista 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