Observera att detta är en arbetsversion av sidan!
Dölj style3dev.css för att bli av med annoteringarna!

Lektion 5: Enkla klasser.   Obligatorisk redovisning 2

Moment: Enkla klasser: instansvariabler, konstruktorer, metoder.
Begrepp som introduceras: Instansvariabler, konstruktorer, get-metoder, set-metoder, toString-metoden.
Arbetssätt:

Arbeta gärna tillsammans med någon men skriv egen kod. Diskutera med varandra!

Följ kodningsreglerna!

Uppskattad arbetstid: 4 timmar. Notera gärna hur lång tid du själv behöver och framför det vid redovisningen!
Redovisning: Obligatorisk redovisning för lärare/handledare enligt tiderna på kurssidan.

Frågor utan svar ska besvaras vid redovisningen. Fråga handledaren om du inte förstår svaren på frågor med givna svar!

Något om klasser och objekt

Begreppen klass och objekt är bland de mest centrala begreppen i objektorienterad programmering. En klass är en allmän beskrivning, en modell eller mall, av en viss typ av objekt som sedan ett program kan skapa och använda för att utföra en uppgift. Klassen (beskrivningen) finns sparad i en textfil med typen .java. Från klassen kan man sedan skapa ett eller flera objekt. T ex skapade du t1 och t2 som refererar till två objekt som är skapade enligt beskrivningen i klassen Turtle.

De klasser vi hittills har sett är Turtle, World, String (och Math som dock är av liten annan karaktär än de först nämnda).

Andra tänkbara exempel på klasser är Person, Bankkonto, Fordon, Ljussignal, Vektor, Boll, Spelplan, ComplexNumber, ... helt beroende på vad programmet skall handla om.
Observera att alla exempel är substantiv! Detta är signifikativt!

När man skall designa en klass väljer man vilka egenskaper man vill att objekten skall ha. Objekt ur klassen Turtle har egenskaper som position (x- och y-koordinater) i världen, färg, storlek, namn, ...
Egenskaperna representeras av instansvariabler.

Man skall också bestämma vad man vill kunna göra med objekten. Turtle-objekten skall kunna flyttas, vändas, byta färg, ...
Sådana operationer definieras av metoder

För att skapa objekt ur en klass använder man så kallade konstruktorer.
En konstruktor ser ut som en metod men den har samma namn som klassen och ingen typangivelse (alternativt uttryckt har den bara en typangivelse (klassnamnet) och inget namn).

Exempel på konstruktorer som du redan har använt:

public World(int x, int y) { ... } En konstruktor i World-klassen.
Parametrarna anger höjd och bredd.
public World() { ... } En annan konstruktor i World-klassen.
Skapar värld av "standardstorlek".
public Turtle(World w) { ... } En konstruktor i Turtle-klassen.

Objekt skapas med operatorn new följt av klassnamnet samt eventuella parametrar inom parentes.

Fråga: Vilka av konstruktorerna används i nedanstående satser?

World w = new World(1000,200); Skapar en värld.
World v = new World(20,20); En till, mycket liten, värld
Turtle t = new Turtle(w); En padda i den stora vida världen
Turtle s = new Turtle(v); och en i den lilla världen
Turtle u = new Turtle(new World()); och en i en ny (skön) värld.

(Observera hur vi på den sista raden anropar konstruktorn för världen i parametern till paddan. Vi skapar alltså en värld utan att själva behålla en referens till den. I detta fall vet vi från föregående lektioner att det går att får tag i en referens med anropet u.getWorld().)

Vi har i tidigare lektioner kompletterat klassen Turtle med några metoder utan att egentligen gå in på hela klassens innehåll. Nu skall vi titta på närmare på hur klasser är uppbyggda.

Klassens allmänna struktur:

public class klassnamn {
instansvariabler beskriver egenskaper hos ett objekt
konstruktorer definierar vad som sker när objektet skapas
metoder definierar vad man kan göra med objektet
}

Uppgift 1: Klassen Rectangle

Antag att vi vill representera rektanglar i ett program. Två fundamentala egenskaper hos rektanglar är bredd och höjd.

Från dessa kan andra egenskaper beräknas (t ex yta och omkrets). Sådana egenskaper kallas härledda.

Rektanglar kan även ha andra egenskaper som t ex färg och position beroende på vad man vill göra med dem men i detta exempel begränsar vi oss till ovan nämnda egenskaper.

I detta lilla exempel ska man kunna skapa rektanglar med olika värden på bredd och höjd, fråga en rektangel om dess egenskaper och ändra vissa egenskaper.

public class Rectangle { Första raden definierar klassens namn.
private double width; private double height; Klassen har två instansvariabler ("egenskaper").
public Rectangle() { width = 1; height = 1; } En parameterlös konstruktor som konstruerar en "enhetsrektangel".
public Rectangle(double width, double height) { this.width = width; this.height = height; } En konstruktor där man anger bredd och höjd.
Se nedan för betydelsen av this.
public double getWidth() { return width; } public double getHeight() { return height; } public double getArea() { return width*height; } Metoder för att hämta egenskaper.
En av egenskaperna (getArea) är härledd.
public void setWidth(double width) { this.width = width; } public void setHeight(double height) { this.height = height; } Två set-metoder för att ändra egenskaperna.
public String toString() { return "Rectangle(" + width + "x" + height + ")"; } En metod som returnerar en text-representation av objektet.
public static void main(String[] arg) { Rectangle rec1 = new Rectangle(); rec1.setWidth(4); rec1.setHeight(5); System.out.print(rec1.toString()); System.out.println(" has the area " + rec1.getArea()); Rectangle rec2 = new Rectangle(3, 2); System.out.print(rec2.toString()); System.out.println(" area " + rec2.getArea()); } } En main-metod som demonstrerar användningen av klassen.







Observera att det går bra att dela upp långa satser på flera rader!






Några allmänna observationer och kommentarer

Gör följande

  1. Välj i DrJava-menyn för att få en tom definitionsruta. Hämta koden och klistra in den i definitionsrutan.
  2. Kompilera.
  3. Eftersom main-metoden ligger i klassen kan man köra den med på klassen. Prova! Studera utskrifterna!
  4. Notera ordningen på klassens delar. Vad händer om man byter plats på metoderna setHeight och getArea? Vad händer om man flyttar instansvariablerna sist i klassen? Varför har man en viss ordning på delarna i klassen?
  5. Skriv en ny metod getCircumference i klassen Rectangle som beräknar och returnerar omkretsen av rektangeln. Metoden ska inte skriva ut något. Kompilera.
  6. Lägg till kod i main som beräknar och skriver ut rektanglarnas omkrets.

Frågor

  1. Vilka instansvariabler har klassen? Svar
    width och height
  2. Vilka lokala variabler finns i koden? Svar
    Endast rec1 och rec2 i main-metoden.
  3. Vilka formella parametrar finns i koden? Svar
    width och height är formella parametrar till den ena konstruktorn. Metoden setWith har width, metoden setHeight har height och metoden main har arg som formell parameter.
  4. Vilka aktuella parametrar finns i koden? Svar
    Aktuella parametrar är de som anges när en metod anropas. I detta exempel är det endast main-metoden som anropar metoder. Aktuell parametrar där är

    4 till setWidth
    5 till setHeight
    rec1.toString() till System.out.print
    "has the area " + rec1.getArea() till System.out.println
    osv.

  5. Vilken del av klassen används när första satsen i main-metoden körs (exekveras)? Svar
    Den parameterlösa konstruktorn i klassen Rectangle anropas och utförs. Rektangelns bredd och höjd sätts till 1. En referens till den konstruerade rektangeln lagras i variabeln rec1.
  6. Vilken del av klassen används när andra satsen i main-metoden körs? Svar
    Metoden setWidth anropas. Metoden ändrar bredden på det nyss skapade rektangelobjektet från 1 till 4.
  7. Vad händer när en konstruktor anropas? Svar
    Ett objekt skapas dvs det reserveras utrymme i minnet för instansvariablerna och dessa tilldelas värden enligt koden i konstruktorn (eller enligt de standardregler som gäller).
  8. Varför behöver metoden setWidth en parameter men inte metoden getArea? Svar
    Parametrar används för att överföra information från anroparen till metoden. setWidth behöver information om vad bredden ska sättas till.
    getArea behöver inget från anroparen utan ska bara lämna ut information om objektet.
  9. Varför har metoden getArea returtyp double och inte void som vissa andra metoder? Svar
    getArea ska returnera information till anroparen men det ska inte setWidth.
  10. Vad händer om man tar bort this från metoden setWidth? Testkör och förklara!
  11. Vad händer om man flyttar this till högersidan av tilldelningen dvs skriver
    width = this.width
    i metoden setWidth? Testkör och förklara!
  12. Kommentera bort definitionen av toString-metoden, kompilera och kör. Vad händer? Varför?
  13. Vad händer om man tar bort anropet till toString()-metoden vid anropen till println i main dvs skriver
    System.out.println(rec1);
    Testkör och förklara!
  14. Läs kodningsreglerna och kritisera nedanstående rader:
    int i = 0; //antal vinster nollställs //nu ska vi öka i med 1 i++; System.out.println(i); //Nu skriver vi ut antalet vinster
    Hur bör koden skrivas? Svar
    Svar:

    Dåligt variabelnamn,
    konstigt sätt att sätta i till 1,
    dålig indentering,
    onödig blankrad,
    totalt onödiga kommentarer,
    användande av nationella bokstäver,
    kommentarerna stör läsbarheten av koden,
    ingen förklaring vad utskriften betyder.

    Så här bör det vara:

    int lotteryWin = 1; System.out.println("Antal vinster: " + lotteryWin)

Uppgift 2: Klassen Person

Skriv en ny klass Person. Följande privata instansvariabler ska finnas (välj lämpliga datatyper själv):
name
address
age

Klassen ska även innehålla:

Observera att ingen av ovanstående metoder ska ge någon utskrift!

Skriv slutligen en main-metod i en annan ny klass som testar metoderna i klassen Person.

Frågor:

  1. Vilken/vilka av ovanstående metoder kan skrivas som void-metoder? Svar
    increaseAge och main
  2. Vilken/vilka av ovanstående metoder måste skrivas som void-metoder? Svar
    Endast main. Man kan t ex låta increaseAge returnera den nya åldern.
  3. Vad får address-variabeln för värde när den parameterlösa konstruktorn använts? Svar
    En instansvariabel av typen String får, liksom alla referensvariabler, värdet null som default.

Uppgift 3: Klasserna Dice och PairOfDice

Klassen Dice

  1. Tag en egen kopia av klassen Dice.java
  2. Kompilera
  3. Klassen innehåller en main-metod som använder klassen. Testkör main-metoden.
  4. Lägg till en metod public int roll(int n) som slår tärningen n gånger och returnerar summan av poängen. Använd metoder som redan finns i klassen Dice istället för att upprepa kod!
    Testa metoden i interaktionsfönstret.
  5. Lägg in anrop av metoden roll(int n) sist i main-metoden. Testkör!

Frågor

  1. Hur fungerar metoden roll()?
  2. Beskriv sats för sats vad som händer när main-metoden körs. (Läs minilektionen om minilektionen om for-satsen om du inte känner till den!)
  3. Vad händer när man exekverar följande satser?
      Dice d = new Dice(1);
      Dice e = new Dice(8);
    		

Klassen PairOfDice

Skriv en ny klass PairOfDice som representerar ett tärningspar (två tärningar). Klassen skall bygga på klassen Dice vilket betyder att man skall använda Dice-objekt och deras metoder. Klassen PairOfDice skall alltså ha två instansvariabler som av typen Dice.

Klassen skall innehålla

Uppgift 4: Klassen Car (Behöver ej redovisas)

Skapa klassen Car ( i DrJava-menyn). Klistra in skelettkoden som finns här. Fyll i där det står punkter (...). Se main-metoden som står sist i klassen för tips hur man skriver klassen.

Fråga

Hur många timmar har du hittills arbetat vid dator med just denna lektion?

 


Gå till nästa lektion eller gå tillbaka

Valid CSS!