jonas.kvarnstrom@liu.se 2014 TDDD78 Introduktion till OOP i Java
Klasser Bilar är komplicerade vi tar cirklar som exempel 3
En klass i Java 4 För att modellera cirklar som objekt i Java: Skapa en cirkelklass Varje Java-klass är i sin egen fil, med "samma" namn (Avancerat undantag: nästlade klasser) Circle.java Definiera fält (se del 2) Definiera konstruktorer (se del 4) Definiera metoder (se del 3) Medlemmar Klassnamn använder "CamelCase": ArrayList, ProcessBuilder, StackTraceElement I singular: Inte Circles, Towers eller ArrayLists!
Egenskaper Vi har nämnt att mojänger/objekt har egenskaper Vissa kan vara konstanta, andra kan ändras efter att objektet skapas 6 Längd/höjd Färg Motorstyrka Toppfart Nuvarande fart Kvarvarande bränsle Koordinater (x,y) Radie (r)
Fält i en klass 7 Realisera egenskaperna som fält (medlemsvariabler) i en klass All kod för klassen är inuti klassdeklarationen Circle.java double x, y; double r; Detta är en klass som talar om vilken sorts information alla cirkelobjekt ska innehålla Ännu har vi inte skapat någon cirkel! Ange datatyp för varje fält: double = 64-bitars flyttal medlemsvariabel = member variable fält = field klass = class
Namngivning Namngivning för fält: Ge beskrivande namn x,y,r OK, vedertagna förkortningar temp, foo, bar inte bra, vad är detta? index eller selectedindex? left eller livesleft? s=52 eller decksize=52? Använd Javas standard! Bra namn färre kommentarer behövs! Sträva efter självdokumenterande kod! 8 Variabler, fält, metoder: main(), args, tvåplustvå, out, println() addelement(), arraylength, allautomförstabörjarmedstor
Fält i objekt 9 Varje objekt vi skapar får sin egen kopia av fälten Alla cirklar har en radie Alla cirklar har varsin radie (Hur skapar man objekt? Med "new" detaljer diskuteras senare!) Datorns minne Object (data) header: x 12.7 y 4.512 r 0.0002 8-16 bytes "intern info" för Java 3*8=24 bytes för fälten Object (data) header: x 23.9 y 3.222 r 12.7 [Python2: Overhead >300 bytes, fält 72 bytes]
Tillstånd (state) 10 Varje objekt har ett nuvarande tillstånd (state) Avgörs av nuvarande värdet på samtliga fält (även de konstanta) Datorns minne Object (data) header: x 12.7 y 4.512 r 0.0002 Object (data) header: x 23.9 y 3.222 r 12.7 Två distinkta objekt med olika tillstånd tillstånd = state
Samma tillstånd Två distinkta objekt i minnet kan ha samma tillstånd Precis som två variabler kan ha samma värde x=10 y=10 x = y, men x och y är ändå olika variabler! Python: a = ("hello", "world") b = ("hello", "world") två olika listor med samma element b.append("again") bara b ändras, inte a a och b var olika listor på olika plats i minnet Datorns minne Object (data) header: x 12.7 y 4.512 r 0.0002 Object (data) header: x 12.7 y 4.512 r 0.0002 11 Samma tillstånd, men inte samma objekt
Byta tillstånd I många klasser kan objekten byta tillstånd när tiden går Datorns minne Datorns minne 12 Object (data) header: x 12.7 y 4.512 r 0.0002 Ändra värdet på y Object (data) header: x 12.7 y 8.328 r 0.0002 Fortfarande samma objekt men nytt tillstånd!
Final Om ett fält inte får/ska ändras efter att objektet skapats: Deklarera det final Person.java class Person { final String personnummer; Person(String personnummer) { this.personnummer = personnummer; 13 Circle.java final double x, y; final double r; Allt är final klassens objekt är immutable ( oföränderliga)
Punktnotation Använd punkt för att komma åt ett fält i ett objekt Fler exempel när vi pratar om metoder 14 Circle.java double x, y; double r; static void print(circle circ) { System.out.println("Hey! You gave me a circle!"); System.out.println("Its radius is " + circ.r);
Att gömma data 15 Fält har skyddsnivåer: private bara klassens egna metoder kan komma åt fältet Klassen har full kontroll oftast bra! public alla kan komma åt fältet Princip: Ju färre som kommer åt något, desto enklare att verifiera, ändra T.ex. svårt att ändra datatyp senare annan kod kan kräva att x är double (protected, "package-protected" senare) Circle.java public // Klasser är oftast public private double x, y; private double r; Vi ignorerar detta i många exempel återkommer senare
Beteenden 17 Objekt i verkligheten gör saker, har beteenden Spontant, "aktivt": Kamelen väljer att spotta Inte del av "vanlig" OO Se multitrådning Reaktivt, på begäran: Tryck på tutan bilen tutar Uppnås via metoder (methods) som kan anropas
Metoder Varje cirkel ska kunna beräkna sin area Deklarera en metod som returnerar detta Metoder placeras oftast efter fält 18 Circle.java double x, y; double r; double getarea() { return Math.PI * r * r; void setradius(double newr) { r = newr; Alltid ett returvärde (typ eller void) Parametrar har typer, namn Metod utan sidoeffekter: Påverkar inget, informerar bara Metod med sidoeffekter: Ändrar något (i detta objekt / på annan plats) sidoeffekt = side effect
Metodkroppen I metodens kropp (body) anges vad metoden ska göra Som i en "vanlig" funktion med en skillnad: Circle.java 19 double x, y; double r; double getarea() { return Math.PI * r * r; void setradius(double newr) { r = newr; Kan direkt komma åt objektets fält! Men i vilket objekt? Vi deklarerar "r" en enda gång. Vi kan skapa 1000 cirklar, och var och en har en egen radie!
This 1: Detta objekt 20 Om vi tar bort "förkortningar": Circle.java double x, y, r; double getarea() { return Math.PI * this.r * this.r ; public static void main(string[] args) { Circle c1 = ; Circle c2 = ; double a = c1.getarea(); double b = c2.getarea(); "r" är en förkortning för "this.r" Fältet "r" i objektet "this" men vad är "this"? "this" är objektet vars metod anropades! I första anropet: this är samma objekt som c1 I andra anropet: this är samma objekt som c2 Ett objekt kan ha många "namn", giltiga i olika delar av koden!
This 2: Omskrivning Nästan som om kompilatorn skrev om koden Adderade en this-parameter till varje metod 21 double x, y, r; double getarea() { return Math.PI * this.r * this.r ; public static void main(string[] args) { Circle c1 = ; double a = c1.getarea(); "Implicit parameter": this double x, y, r; double getarea(circle this) { return Math.PI * this.r * this.r; public static void main(string[] args) { Circle c1 = ; double a = getarea(c1); (Nästan: Det finns viktiga skillnader, t.ex. i ärvning)
This 3: Utelämna this 22 Kan ofta utelämna this Givet en identifierare "r" söker kompilatorn efter: 1. Lokala variabler och parametrar "r" 2. Fält "r" double x, y, r; double getarea() { return Math.PI * this.r * this.r ; public static void main(string[] args) { Circle c1 = ; double a = c1.getarea(); "Det finns inget r, så de måste mena this.r " double x, y, r; double getarea() { return Math.PI * r * r; public static void main(string[] args) { Circle c1 = ; double a = c1.getarea();
This 4: Gömda fält Men variabler och parametrar gömmer fält ("hiding") 23 double x, y, r; Olika namn (r, newr) void setradius2(double newr) { System.out.println(r); // Finns variabel/parameter? Nej! Skriv ut fältet r = newr; // Sätter fältets värde double x, y, r; void setradius2(double r) { System.out.println(r); System.out.println(this.r); r = r; this.r = r; Samma namn (r), parameter gömmer fält // Finns variabel/parameter? Ja! Skriv ut den // Måste vara fältet // Sätter argumentet till sitt eget värde // Sätter fältets värde
Namngivning Namngivning: Som för fält: Ge beskrivande namn update() eller moveplayer()? doit() eller shuffledeck()? units() eller setunittype()? 24 Använd Javas standard! Variabler, fält, metoder: main(), args, tvåplustvå, out, println() addelement(), arraylength, allautomförstabörjarmedstor
Namngivning 2: Overloading Metoder kan överlagras (overloading) Olika metoder i samma klass med samma namn class Printer { void print(int val) { void print(double val) { void print(double val, int precision) { Skiljs åt av antal argument + argumenttyperna Användning: När metoderna gör i princip samma sak När det vore onödigt krångligt att hitta på egna namn (printint, printdouble, ) 25
Metodlängd (1) Hur lång får en metod vara? "The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that. Functions should not be 100 lines long. Functions should hardly ever be 20 lines long." -- Robert Martin, Clean Code: A Handbook of Agile Software Craftsmanship 26 "The routine should be allowed to grow organically up to 100-200 lines. Decades of evidence say that routines of such length [are] no more error prone than shorter routines." -- Steve McConnell, Code Complete
Metodlängd (2) Varför dessa motsatser? 27 Ju fler kockar desto sämre soppa Fyra ögon ser bättre än två För varje regel finns en lika stark och motsatt motregel
Metodlängd (3) 28 Målet: Kod ska vara läsbar, lätt att förstå, lätt att underhålla Långa metoder Bryt ut delar svåra att hålla reda på, bryt ut delar till egna metoder! kan tappa sammanhanget, svårt att förstå Korta metoder Många metoder lättare att läsa mer att hålla reda på Väg kriterierna mot varandra Och var inte för extrema åt något håll! Hitta rätt balans, utgå från målet istället för medlet! Men: Vi måste ofta ge komplettering för "för långa" metoder (100-300 rader) Vi har sällan gett komplettering för "för korta" metoder
Skapande Att skapa nya listor, tupler osv. i Python: 30 tomlista = [] minlista = ["a", "b", "c"] mintupel = (12, 34, 56) mindict = { "a": 1, "b": 2 Egen syntax för varje typ Ange alla element som listan / tupeln / ska innehålla
Skapa objekt 1 31 Hur skapar man nya objekt? Generell "objektsyntax", ange värdet på varje fält? Circle mycircle = Circle[[12.7, 4.512, 0.0002]]; Datorns minne Object (data) header: x 12.7 y 4.512 r 0.0002 Nej: Många klasser har fält som ska beräknas eller kan lämnas tomma eller är privata för internt bruk Måste kunna välja vilka fält vi sätter
Skapa objekt 2 32 Hur skapar man nya objekt? Först skapa "nollställt" objekt, med alla fält "nollställda", sedan sätta önskade värden utifrån? Circle mycircle; mycircle.x = 10; mycircle.y = 20; Nej: Tillåter godtyckliga värden Listor kan innehålla vad som helst Men cirklar ska ha radie > 0 Klassen ska kunna garantera detta! Datorns minne Object (data) header: x 0 y 0 r 0 Fundamental princip: Klassen bestämmer över sina objekt (kan förhindra manipulation utifrån
Konstruktorer 1 Låt klassen ange konstruktorer, speciella metoder för att initialisera objekt 33 double x, y, r; Ingen returtyp (inte void!) Samma namn som klassen Circle(double x, double y, double radius) { Detta är en konstruktor! konstruktor = constructor
Konstruktorer 2 Ibland vill vi: Kunna sätta specifika värden på alla fält 34 double x, y, r; En parameter per fält Circle(double x, double y, double radius) { this.x = x; this.y = y; En tilldelning per fält; this.r = radius; "this" är det nya objektet public static void main(string[] args) { Circle c1 = new Circle(10.0, 20.0, 14.2); Vi anropar konstruktorn med new och anger lämpliga parametrar
Konstruktorer 3: Vad händer? 35 1: Minne allokeras (reserveras) för objektet 2: Alla fält får defaultvärden Heltal: 0 Floating point: 0.0 Boolean: Objekt: false 3: Konstruktorn anropas null (diskuteras senare) Object header: x y r (skräp) (skräp) (skräp) (skräp) Object Circle header: x 0.0 y 0.0 r 0.0 Circle(double x, double y, double radius) { this.x = x; this.y = y; this.r = radius; Fundamental princip: Klassen bestämmer över sina objekt klassen anger konstruktorkoden!
Konstruktorer 4: Kontroller Ibland vill vi: Kontrollera att bara tillåtna värden anges 36 double x, y, r; Circle(double x, double y, double radius) { if (radius <= 0.0) { Se till att radien > 0, throw exception ; annars avbryts konstruktorn inget objekt skapas this.x = x; this.y = y; this.r = radius;
Konstruktorer 5 Ibland vill vi: Ta in värden i annat format än det klassen använder 37 double x, y, r; Circle(Point center, double radius) { if (radius <= 0.0) throw ; this.x = center.x; this.y = center.y; this.r = radius; Anta en "punktklass" som lagrar x, y Ta ut x och y från "centrumpunkten"
Konstruktorer 6 Ibland vill vi: Beräkna värden på fält från andra parametrar 38 double x, y, r; double area; Circle(double x, double y, double circumference) { if (circumference<= 0.0) throw ; this.x = x; this.y = y; this.r = circumference / (2*Math.PI); Beräkna radie från omkrets this.area = Math.PI * r * r; Beräkna area från radie
Konstruktorer 7 Ibland vill vi: Sätta värden själva eftersom de är "interna" detaljer, inte något som anroparen ska bry sig om double x, y, r; int timespainted; Håll reda på antalet gånger vi har ritat cirkeln (statistik) 39 Circle(double x, double y, double radius) { this.x = x; this.y = y; this.r = radius; this.timespainted = 0; Från början är antalet alltid 0
Konstruktorer 8 En konstruktor kan göra vad som helst 40 double x, y, r; boolean debug; Circle(double radius) { System.out.println("Hello, world!"); System.exit(0); Inte vad man ska göra, men man kan
Konstruktorer 9: Kopiering Ibland kan man vilja kopiera objekt Konstruktor som tar ett objekt av samma typ 41 double x, y, r; Circle(double x, double y, double radius) { this.x = x; this.y = y; this.r = radius; Circle(Circle other) { this.x=other.x; this.y=other.y; this.r=other.r; Kopieringskonstruktor: Tar ett objekt av samma typ
Konstruktorer 10: Overloading En klass kan ha flera konstruktorer Alla heter samma som klassen overloading 42 double x, y, r; Circle(double x, double y, double radius) { this.x = x; this.y = y; this.r = radius; Circle(Point center, double diameter) { this.x = center.x; this.y = center.y; this.r = diameter / 2;
Konstruktorer 11: Minst en! Varje klass har minst en konstruktor Har du inte skrivit någon? Då skapar Java en tom konstruktor utan argument! double x, y, r; 43 double x, y, r; public Circle() { // Gör ingenting // alla fält har defaultvärden (0, 0.0, false, )
Nu: Tillräckliga kunskaper för labb 2 Programmering och OO: Viktiga begrepp Kontrakt Annoteringar Gömma information inkapsling Pekare allmänt och i Java Objektorientering: Typhierarkier och ärvning (drygt 1 fö) Gränssnitt Liskov Substitution Principle Subtypspolymorfism Ärvning mellan gränssnitt; mellan klasser Abstrakta klasser Egenskaper hos Javas klasshierarki Tillräckliga kunskaper för labb 3 Programmering och OO: Viktiga begrepp Identitet och likhet Lagring och livstid olika sorters variabler Metoder utan objekt (+ intro till Tetris-labben) Tillräckligt för början av labb 4
GUI-programmering i Java, del 1 GUI-programmering i Java, del 2 Tillräckligt för hela labb 4