Fält av referenser Tanken med objekt är man kan bygga ihop olika sorts objekt till nya saker. Sålunda kan man exempelvis använda Bil och Trafikljus att konstruera ett Väg-objekt. Om Bil och Trafikljus är gjorda med lite eftertanke och tillräckligt generella så är det bara att använda dem. För att göra det måste man veta: Vilka konstruktorer finns? Vilka metoder finns? Konstruktorerna används för att skapa Bilar och Trafikljus. Metoderna används för att få objekten att utföra olika saker. Java hittar automagiskt alla klasser som du skrivit som ligger i din arbetskatalog. Du behöver alltså inte tala om för Java var Bil och Trafikljus finns så länge du håller dig i samma katalog. Om du vill arbeta i flera olika kataloger så måste du tala om för Java var den ska leta. Det gör du med omgivningsvariabeln CLASSPATH. Under lab 0 har du satt upp en standard sådan i filen.bash_profile i din hemkatalog. Du kan vid behov ändra detta (med försiktighet). Fält av referenser 22 October 2003 1 Fält av referenser 22 October 2003 2 Vi vill nu göra ett personregister. Det ska bestå av en massa personer. Vi vill kunna lägga in personer, söka efter personer, ta bort personer, skriva ut personer m. m. Vi börjar med att göra en Personklass. Den ska kunna utföra allt vi vill göra med personer. Kom ihåg nu att vi bara gör en ritning nu, ingen skapar några personer, ingen gör nåt med personer. Vi bara beskriver nu. Vi ska alltså inte bekymra oss om vem som gör nåt och varför. Svaret på såna frågor är att ingen gör nåt eftersom det inte finns något att arbeta med. Instansvariabler ska beskriva personen. Vi kan exempelvis ha: Namn, Sträng Adress, Sträng Personnummer, Sträng Inkomst, Heltal Ålder, Heltal Vikt, Heltal Rökarstatus, Boolean Det ger nåt sånt här: public class Person { private String namn; private String adress; private String personnummer; private int inkomst; private int ålder; private int vikt; private boolean rökare;... Sen funderar vi över konstruktorer. Ska vi ha en standardkonstruktor? Vad är det? Vad ska vi ha mer? Fält av referenser 22 October 2003 3 Fält av referenser 22 October 2003 4
Det finns ju uppenbarligen inget sätt att standardisera personer så att det finns en standardperson. Det gör att vi kanske inte ska ha nån standardkonstruktor. Om vi inte har det kan vi INTE göra Person p = new Person(); utan måste använda nån annan konstruktor där vi måste ange värden för en del eller alla instansvariabler. Exempelvis Person p = new Person( Nisse, Storgatan 3, 710332-3451, 345000, 32, 78, false); Hur vi än vänder oss så måste vi ju på nåt sätt ange värden till alla instansvariablerna om vi ska få en användbar person. Det kan vi förutom via en konstruktor göra via inläsning till ett befintligt objekt (dvs ett som skapats med en konstruktor). Det kan alltså vara vettigt att ha en standardkonstruktor som sätter upp ett objekt som vi sen kan fylla i på nåt annat sätt. Ger oss public Person() { namn = NN ; adress = ; personnummer= 000000-0000 ; de vi inte anger blir 0 automagiskt public Person( String namn, String adress, String personnummer, int inkomst, int ålder, int vikt, boolean rökare) { this.namn = namn; this.adress = adress; this.personnummer = personnummer; this.inkomst = inkomst; this.ålder = ålder; this.vikt = vikt; this.rökare = rökare; Fält av referenser 22 October 2003 5 Fält av referenser 22 October 2003 6 Hur tolkar vi den andra konstruktorn. Vad betyder det att vi har samma namn både här och där? Deklarationen av konstruktorn betyder: Nu kan du skapa ett objekt av typen person. För att du ska kunna göra detta har jag fixat sju lådor i minnet som heter namn, adress, personnummer, inkomst, ålder, vikt och rökare. I dessa lådor ska du lägga de värden du vill ha i ditt objekt. Sen är det mitt (konstruktorns) ansvar att tömma dessa lådor och lägga innehållet i instansvariablerna. Dessa kan vi ju också se som namngivna lådor i minnet. De har just här exakt samma namn som ovanstående men en helt annan funktion. Parametrarna: en tillfällig låda där jag kan lägga värden som jag vill att konstruktorn ska använda, när den gjort det är lådorna bortsopade. Instansvariabler: en låda som finns så länge objektet finns. De beskriver objektet, ges initialvärde av konstruktorn. Konstruktorn kopierar parametrarna till instansvariablerna. Det måste göras med en tilldelning. Att de har samma namnuppsättning ändrar inte det, det komplicerar det bara lite. Eftersom parametrarna står i konstruktorn så är det de som syns bäst. Om jag anger namnen namn, adress m. fl så är det parametrarna jag menar, de har gömt instansvariablerna. För att komma åt instansvariablerna så måste jag här kvalificera mig, jag sätter this framför, det betyder alltid att det är instansvariabler eller metoder jag menar. Om jag inte använder samma namn uppstår ingen tvetydighet och this behövs inte, men kan användas. Fält av referenser 22 October 2003 7 Fält av referenser 22 October 2003 8
Sen behöver vi ett antal metoder: Vi behöver kunna läsa av och ändra olika instansvariabler. Vi vill kunna skriva ut en person (tostring) Vi vill kunna fråga efter vad instansvariablerna i ett befintligt objekt ska ändras till Vi vill kunna avgöra sorteringsordning mellan två personer. Exempelvis: public String hämtanamn() { return namn; public void bytnamn(string nyttnamn) { namn = nyttnamn; // osv public String tostring() { return Namn: + namn + \n + Adress: + adr ess + \n + Pers. no.: + personnummer + \n + Inkomst: + inkomst + \n + Ålder: + ålder + \n + Vikt: + vikt + \n + Rökare: + rökar e + \n ; Fält av referenser 22 October 2003 9 Fält av referenser 22 October 2003 10 public void läsin() { Std.out.print( Namn? ); namn = Std.in.readLine(); Std.out.print( Adress? ); adress = Std.in.readLine();... Std.out.print( Vikt? ); vikt = Std.in.readInt(); Std.out.print( Rökare J/N? ); String svar; svar = Std.in.readWord(); if (svar.equals( J )) rökare = true; else rökare = false; Std.in.skipLine(); Hur kan vi jämföra två personer? Till att börja med måste vi ju ha två personer för att kunna jämföra. Det betyder att vi gör en metod i person som har en annan person som parameter. Vi jämför dessa och ger ett svar. Hur jämför vi? Det finns ju inget givet sätt, det får du avgöra. Man tänka sig bokstavsordning efter namn, åldersordning, viktordning m.m. Vi bestämmer att vi använder bokstavsordning efter namnet. Java använder oftast en metod som heter compareto för att jämföra saker. Vi gör lika eftersom vi inte är anarkister. Fält av referenser 22 October 2003 11 Fält av referenser 22 October 2003 12
public int compareto(person p) { // // jämför mitt namn med p s namn // använd metoden compareto i // strängklassen return namn.compareto(p.namn); Nu har vi skapat en personklass som går att använda till lite allt möjligt. public class PTest { public static void main(string [] args) { Person p1, p2; p1 = new Person(); p2 = new Person( Nisse, Stor gatan 3, 710332-3451, 345000, 32, 78, false); // fyll i p1 p1.läsin(); if (p1.hämtarökare()) Std.out.println( p1.hämtanamn() + röker ); // jämför och testa tostring if (p1.compareto(p2) < 0) Std.out.println(p1 + \nkommer före\n + p2);... Fält av referenser 22 October 2003 13 Fält av referenser 22 October 2003 14 Nu vill vi alltså göra ett register av personer. Det liknar ju i nån mening att göra en Väg av Bilar och Trafikljus. Registret ska ju innehålla många personer, alltså en array av Personer. Vi skapar plats för många men har nog färre personer lagrade. Därför måste vi både hålla ordning på fältets storlek och antalet personer som vi just nu har lagrat. public class Register { private Person [] reg; private int antal; public Register() { reg = new Person[100]; // max 100 pers antal = 0; // inga alls ännu Nu behöver vi metoder också: sökning inläggning borttagning utskrift sökning, ange ett namn, se om det finns nån som heter så public int sök(string namn) { int plats = 0; while (plats < antal) { if(reg[plats].hämtanamn().equals(namn)) return plats; else plats++; return -1; blir det inte trassel med parametern namn här? Nej namn finns som instansvariabel i Person, inte i Register. Fält av referenser 22 October 2003 15 Fält av referenser 22 October 2003 16
Utskrift: Gå igenom alla personerna och producera en sträng m. h. a. tostring. public String tostring() { String s = ; for (int i = 0; i < antal; i++) s = s+ reg[i].tostring(); return s; Inläggning: Utgå från att vi får ett färdiggjort personobjekt som bara är att stoppa in i registret. På så vis blir det inte så många parametrar. Vi vill ha personerna i ordning. Kollar inte att registret blir fullt! public void läggin(person p) { if (antal == 0) { reg[0] = p; antal++; return; else { // leta upp rätt plats int plats = 0; while (plats < antal && reg[plats].compareto(p) < 0) plats++; // flytta undan för att ge plats for (int i = antal; i > plats; i--) reg[i] = reg[i-1]; // lägg in reg[plats] = p; antal++; Fält av referenser 22 October 2003 17 Fält av referenser 22 October 2003 18 ta bort: public void tabort(string namn) { // leta int plats = sök(namn); if (plats < 0) Std.out.println(namn + finns inte ); else { for (int i = plats; i < antal - 1; i++) reg[i] = reg[i+1]; antal--; Kan vi testa så här public class RegTest { public static void main(string [] args) { Register r = new Register(); Person p = new Person("Uppfinnarjocke, "Ankeborg", "710332-3451", 345000, 32, 78, false); r.läggin(p); Std.out.println(r); // skriv ut // finns han? Std.out.println(r.sök(p.hämtaNamn())); // skapa 3 personer for (int i = 1; i <= 3; i++) { Person p1 = new Person(); p1.läsin(); r.läggin(p1); Std.out.println(r); // skriv ut // ta bort Misse Pugg om han finns r.tabort("musse Pigg"); Std.out.println(r); // skriv ut Fält av referenser 22 October 2003 19 Fält av referenser 22 October 2003 20
Kan ge oss > javac RegTest.java > java RegTest Namn: Uppfinnarjocke Pers. no.: 710332-3451 Inkomst: 345000 Ålder: 32 Vikt: 78 0 Namn? Kalle Anka Adress? Ankeborg Personnummer 320123-3432 Inkomst? 345123 Ålder? 71 Vikt? 34 Rökare J/N? N Namn? Musse Pigg Adress? Ankeborg Personnummer 280423-5432 Inkomst? 789654 Ålder? 75 Vikt? 23 Rökare J/N? N Namn? Joakim von Anka Adress? Ankeborg Personnummer 101010-1010 Inkomst? 1234567544 Ålder? 93 Vikt? 45 Rökare J/N? N Namn: Joakim von Anka Pers. no.: 101010-1010 Inkomst: 1234567544 Ålder: 93 Vikt: 45 Namn: Kalle Anka Pers. no.: 320123-3432 Inkomst: 345123 Ålder: 71 Vikt: 34 Namn: Musse Pigg Pers. no.: 280423-5432 Inkomst: 789654 Ålder: 75 Vikt: 23 Namn: Uppfinnarjocke Pers. no.: 710332-3451 Inkomst: 345000 Ålder: 32 Vikt: 78 Fält av referenser 22 October 2003 21 Fält av referenser 22 October 2003 22 Namn: Joakim von Anka Pers. no.: 101010-1010 Inkomst: 1234567544 Ålder: 93 Vikt: 45 Namn: Kalle Anka Pers. no.: 320123-3432 Inkomst: 345123 Ålder: 71 Vikt: 34 Namn: Uppfinnarjocke Pers. no.: 710332-3451 Inkomst: 345000 Ålder: 32 Vikt: 78 Fält av referenser 22 October 2003 23