Att skapa en klass kvadrat Uppgiften är att beskriva en kvadrat i ett Java program. En första version av programmet skulle kunna se ut så här: public class Kvadrat { private int sida; Det var väl inte så svårt? Eller var det det? Det finns en del att förklara här och jag skall göra ett försök att reda ut det mesta. Jag börjar med att förklara rad för rad för att sedan gå in på vad programmet gör och hur det används. Redan på första raden finns det en hel del att kommentera. På raden står det ju public class Kvadrat { och det kräver lite förklaring. Om vi börjar med public så är det en åtkomstmodifierare. Det finns några olika sådana och här kommer en beskrivning av 2 stycken. 1. Public, betyder att alla kommer åt att använda den. Det räcker med att ha tillgång (veta var det finns) till det som är public så är det ok att använda. 2. Private, betyder att ingen utomstående kommer åt den. Om det, som i detta fallet, är en klass som är private så blir det ju svårt att använda den, ingen har ju rätt att använda den. Nästa ord är det reserverade ordet class. class talar om att det är en klass som vi håller på att definiera. Vi kan i en fil definiera olika saker men vi skall, åtminstone i början av kursen, uteslutande skriva klasser. Sedan står det Kvadrat, det är något som jag hittat på alldeles själv. Det är namnet jag valt på min klass. Namnen på klassen (alltså Kvadrat i detta fallet) skall alltid skrivas med versal som första bokstav, då det är en standard att skriva så. Programmet kanske fungerar med gemen förstabokstav men det blir då bannor från mig Programmet, i sin helhet, skall ligga i en fil som heter samma sak som klassen med extensionen java. Filen som denna kod skall ligga i skall/måste alltså heta Kvadrat.java. Sist på raden är det en liten lustig krumelur ({), jag kallar den för startmåsvinge. Den talar om att själva definitionen av klassen börjar här. Denna startmåsvinge hör ihop med den slutmåsvinge som finns på sista raden i programmet (). Då hoppas jag att första raden är klar. Nästa rad är ju ganska kort men kräver lite förklaring den också. private int sida; beskriver klassens attribut eller egenskap, även kallad instansvariabel. Vad som kännetecknar en kvadrat är ju, i alla fall i min värld, att den har en sida 1(5)
(fyra för att vara noga men alla är ju lika långa). Det har jag beskrivit här. Jag har sagt att sidan är private, dvs ingen utanför kan ändra eller läsa av värdet. När det gäller attribut (egenskaper) så är den väldigt vanligt att man sätter dem till private, detta för att få kontroll på vem som ändrar eller läser av värdet. int är ett reserverat ord som betyder att mitt attribut är av typen heltal. Eftersom jag sagt att sida skall vara av typen int så kan jag bara tilldela sidan heltal. Men, innan vi går vidare måste vi ta och fundera över en sak. Jag har ju i texten ovan pratat om åtkomstmodifierare. Jag skrev att om man använder modifieraren private så kommer ingen utomstående åt det jag skyddat. Om vi tittar på attributet sida så har jag ju satt det till private. Utomstående i detta fallet är ju då allt som är definierat utanför klassen Kvadrat. Om du som användare skulle vilja läsa av sidan eller om du skulle vilja sätta den till 4 så kan du inte det, du är ju inte en del av Kvadrat! Detta kan man lösa med att göra sida till public men det skall vi INTE! Det blir lite mer arbete i början men vi vinner, tror jag, i längden på att lära oss rätt från början. Svaret är alltså inte att göra sida åtkomlig för allt och alla utan att definiera vägar in och ut. Jag har just sagt att attributet sida skall vara privat. För att kunna komma åt det så skapar jag metoder som är publika. Dessa är då en del av klassen vilket gör att de har tillgång till det privata attributet samtidigt som jag deklarerar dem public, detta gör att jag som användare kommer åt dem utifrån. Jag skapar helt enkelt två metoder, en för att tilldela attributet ett värde (setsida) och en för att fråga efter värdet (getsida). Namnen på metoderna har jag själv valt men jag har följt en standard och döpt dem efter vad de gör. getsida för att hämta värde och setsida för att tilldela (sätta) ett värde. Om vi tittar lite på metoderna så ser den översta ut så här: Om vi som förut förklarar den rad för rad så betyder första raden att: - Den är public. Alla med, i detta fallet, en referens till ett objekt av typen Kvadrat har tillgång till objektets metod setsida. - void. Metoden returnerar inget. Returtypen void betyder att inget returneras. - setsida är det namnet jag valt till metoden. - (int sidain) är metodens parameterlista. I detta fallet tar vi emot ett heltal (int) som vi kallar för sidain. Jag har alltså hittat på detta namnet själv. - { talar om att definitionen av metoden börjar här. Denna definition avslutas med på rad tre. Själva innehållet, vad metoden gör, är inte så mycket att orda om tror jag. När vi anropar metoden skickar vi med ett heltal som vi kallar sidain. Här i metoden sätter vi objektets attribut (sida) till det värde som vi skickat in (sidain). Nästa metod är nästan lika, fast tvärt om. Här är det en metod som är skriven för att tala om vilket värde attributet sida har: 2(5)
Första raden, första ordet (public) kan vi väl vid det här laget. Nästa ord, int, talar om att metoden returnerar ett heltal av typen int. Efter namnet (getsida, som jag själv hittat på) är det tomma parenteser, det visar att getsida är en metod men den tar inte emot något värde. Sedan gör metoden inte mer än att den returnerar värdet på objektets attribut (sida). Detta skulle alltså vara hela klassen. Vi har nu byggt en klass som skall representera en kvadrat. Men hur skall vi använda den då? För att göra det riktigt generellt från början så skapar vi en egen klass för att köra/använda vår Kvadrat-klass. Det enda som behövs är att vi lägger de båda klasserna i samma katalog. I Eclipse innebär det att de skall ligga i samma projekt. Jag skapar alltså ytterligare en klass, denna klass skall alltså använda vår redan kapade Kvadrat-klass. Här kommer klassen: public class Rune { public static void main(string[] args) { Kvadrat k=new Kvadrat(); k.setsida(5); Denna klass skall alltså ligga i en fil som ni döper till t.ex. Rune.java. Namnet har jag själv hittat på och det speglar bara att vi skall använda klassen till att köra (run) någon annan klass. Det enda vi skall lägga i denna klassen är en main-metod, det är en sådan metod som krävs i alla javaprogram för att starta dem. Main-metoden måste se ut som i exemplet ovan (public static void main(string[] args)) för att kompilatorn skall känna igen den. Public vet ni redan vad det betyder, static betyder att metoden är knuten till klassen och inte till ett enskilt objekt. Detta gör att vi kan köra metoden utan att vi skapat något objekt först, men mer om static längre fram i kursen. void betyder, som jag sagt tidigare, att metoden inte skall returnera något värde. main är namnet på metoden, det har inte jag hittat på utan det är ett reserverat ord i Java, det måste finnas minst en mainmetod i alla javaprogram. Innanför parenteserna har vi parametrarna som vi skickar med till metoden, i detta fall skickar vi en vektor av strängar som vi kallar args. Vektorer kommer vi att gå igenom längre fram i kursen. Väl i main-metoden så är det alltså tre satser som skall göras. Den första är Kvadrat k=new Kvadrat(); Och innebär att vi skapar ett Kvadrat-objekt och håller reda på detta objekt med referensen k. Man kan skriva detta på följande vis också, då är det lättare att förklara steg för steg vad som händer: Kvadrat k; k=new Kvadrat(); 3(5)
På första raden skapar jag en referens av typen Kvadrat. Det är alltså en referens som är specialgjord för att referera till objekt av typen Kvadrat. Jag döper min referens till k. På andra raden skapar jag, med hjälp av operatorn new, ett kvadratobjekt. När det är gjort så tilldelar jag (tecknet =) min referens det skapade objektet. Jag har nu en referens som jag döpt till k och som håller reda på ett objekt av typen Kvadrat. Nästa sats i main-metoden är k.setsida(5);. Här använder jag min referens för att vi den komma åt metoden setsida i objektet. Jag skickar med värdet 5, som i objektet sedan tilldelas kvadratens attribut (sida). I sista satsen skriver jag ut värdet på sida. Detta kan jag inte göra i main-metoden så jag går via min referens och metoden getsida. Den metoden är ju public (precis som setsida ovan) vilket gör att jag kan komma åt den via min referens i main-metoden. Ni kan nu provköra programmet (de två klasserna) och se så att det fungerar som ni tänkt. Konstruktorer I kapitel 6.1 går författaren igenom konstruktorer. Här kommer min lite korta genomgång av konstruktorer. Konstruktorn är som vilken metod som helst, fast helt annorlunda Här följer i punktform några egenskaper som konstruktorer har, jämfört med andra metoder: - En konstruktor har ALLTID samma namn som klassen. Eftersom jag sagt att klassen skall ha en inledande versal så har alltså en konstruktor ett namn som inleds med en versal. Om ni följer kodstandarden så kommer en konstruktor att vara den enda metoden som har en inledande versal. - En konstruktor har inget returvärde. Det finns andra metoder som saknar returvärde, alltså att de inte skall returnera något, men då visar vi det genom att returnera void. En konstruktor returnerar inget, inte ens void. - En konstruktor körs alltid automatiskt och först när en klass skapas. I klassen Rune ovan ser ni ett konstruktoranrop (k=new Kvadrat();). Konstruktorn körs alltså när klassen skapas. - Det finns alltid en konstruktor i alla klasser, även i klassen Kvadrat här ovan. Om vi inte gör en egen så finns det alltid en defaultkonstruktor som används. - Man kan ha flera konstruktorer i en klass, då måste de ha unika signaturer. En signatur är namn och parameterlista tillsammans. Jag skall här göra en konstruktorer som visar hur det fungerar. Till vår kvadratklass skulle vi kunna ha följande konstruktor: public Kvadrat(int s){ sida=s; 4(5)
Vad händer om ni testar att lägga till denna konstruktor till klassen Kvadrat? Testa och läs vidare sedan. Det gick inte så bra va? Om ni kör Eclipse så ser ni att det blir ett rött streck under new Kvadrat() i Rune-klassen. Om ni fortsätter ändå så blir resultatet: Exception in thread "main" java.lang.error: Unresolved compilation problem: The constructor Kvadrat() is undefined at Rune.main(Kvadrat.java:16) Vad är det som hänt? Jo, ni har lagt till en egen konstruktor som tar en parameter (int s) men anropar konstruktorn utan några parametrar. Ni måste alltså ändra i anropet så att ni skickar med ett heltal när ni skall skapa klassen. På nästa sida ser ni hur det skulle kunna se ut när ni ändrat. Testa gärna andra alternativ och diskutera era resultat i First Class Fungerande program med en egendefinierad konstruktor: public class Kvadrat { private int sida; public Kvadrat(int s){ sida=s; public class Rune { public static void main(string[] args) { Kvadrat k=new Kvadrat(6); k.setsida(5); Diskutera gärna i First Class, det är när man försöker formulera problemen som man kan lösa dem. Det är också bra med andras åsikter då man kan göra rätt på olika sätt. 5(5)