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

Lektion 3: Mer om metoder

Syfte: Öva villkors- och iterationssatser samt på metoder som returnerar värden. Introducera debugging.
Begrepp som introduceras: Metoder med returtyper, if-satsen, while-satsen.
Arbetsform: Arbeta gärna tillsammans med någon men skriv egen kod. Diskutera med varandra!
Arbetstid: 4 timmar
Redovisning: Ingen obligatorisk redovisning, men diskutera med handledare om det är något du är osäker på!

Lite om klassen Turtle och dess invånare

Antag att vi skapar en värld med satsen World w = new World(200,300);

Världen illustreras av den tvådimensionella rektangel som vi då ser på skärmen. Storleken, som vi ger när vi skapar den, mäts i så kallade pixlar (bildpunkter). Det definierar ett koordinatsystem där origo är i rektangelns övre vänstra hörn. X-axeln går på vanligt sätt åt höger men y-axeln går nedåt (vilket är det vanliga sättet när man talar om koordinater på datorskärmar). Det nedre, högra hörnet har alltså koordinaterna (200, 300) i detta exempel.

När vi skapar sköldpaddor (new Turtle(w)) så berättar vi för dem vilken värld de tillhör (w skickas ju som parameter vid skapandet av paddan) och världen ser då till att placera ut dem på någon koordinat (verkar vara mitt i världen). När vi sedan t ex gör move(50) så flyttas den paddan vi refererar till en annan koordinat.

Man kan fråga en värld (w) om dess storlek med metoderna getWidth() och getHeight() som i detta exempel skulle returnera 200 respektive 300. (I just detta fall vet vi ju var värdena är men man vill kunna skriva kod som som fungerar generellt.)

Metoder som returnerar värde

De flesta metoder som vi hittills skrivit och använt (move, turn, ritaKvadrat, ...) har varit så kallade void-metoder. De gör saker med objekten men returnerar inte något värde. Det går t ex inte att skriva int x = t1.move(50).

Metoderna som nämndes i första stycket (getWidth och getHeight) samt metoderna i klassen Math (Math.sqrt, Math.sin, ...) är exempel på metoder som inte är av void-typ. Gemensamt för dessa är att de returnerar ett värde. Värdet är av typen int för de två först nämnda och av typen double för Math-metoderna. Värdet kan tas emot i en variabel eller direkt användas t ex i en beräkning.

Exempel: ... int area = w.getHeight()*w.getWidth(); ... double squareRadius = Math.sqrt(area); ...

Att en metod returnerar något betyder alltså att den levererar ett värde (heltal, flyttal, objektreferens, ...) till den som anropar metoden.

Det är anroparen ("mottagaren") som avgör vad som ska göras med värdet. Det kan t ex sparas i en variabel, användas direkt i en beräkning, skrivas ut eller, till och med, glömmas bort.

För att skriva metoder som returnerar värden måste man

  1. i metodhuvudet ange värdets typ och
  2. i metodkroppen ha en return-sats som anger vad värdet ska vara.

Ett första exempel

Antag att vi i klassen World vill ha en metod som returnerar världens storlek i "kvadratpixlar". (Vi har inte tidigare skrivit några egna metoder i klassen World men det är ingen skillnad a skriva metoder i klassen Turtle.)
public int area() { int a = this.getWidth()*this.getHeight(); return a; } Metoden ska returnera ett värde av typen int Först beräknas värdet och sedan returneras det.

Prova gärna att klistra in detta i World-klassen och testa i interaktionsrutan!

Anmärkning: Men behöver inte spara resultatet i en variabel. Denna metod skulle kunna ha satsen

return this.getWidth()*this.getHeight();

som enda innehåll.

Ett lite större exempel i två varianter

Vi ska titta på en metod som beräknar en paddas avstånd till origo. Den finns här i två varianter. Metoden i den vänstra rutan returnerar resultatet som ett flyttal (double) medan metoden i den högra rutan returnerar resultatet som ett heltal (int). Koden som skiljer är markerad.
/** * Calculates the distance from the * Turtle to origo. * Returns the distance as a * decimal number. */ public double distanceOrigo() { int x = this.getXPos(); int y = this.getYPos(); //Pythagoras: double d = Math.sqrt(x*x + y*y); return d; }
/** * Calculates the distance from the * Turtle to origo. * Returns the distance as an * integer number. */ public int distanceOrigo() { int x = this.getXPos(); int y = this.getYPos(); //Pythagoras: double d = Math.sqrt(x*x + y*y); int i = (int)d; //Truncate to int return i; }

Det är viktigt att typen på värdet i return-satsen överensstämmer med typen som står i metodhuvudet! Eftersom sqrt-metoden returnerar ett värde av typen double måste vi i den högra metoden explicit konvertera värdet till int.

Övning 1

Testa den vänstra metoden double distanceOrigo().

Kopiera och klistra in den vänstra metoden längst ned i klassen Turtle och kompilera.

Skapa en värld i interaktionsrutan och lägg in en padda t1 och anropa metoden så här:

double d = t1.distanceOrigo(); d Lagra avståndet i en variabel
och titta vad det är.
Observera igen att det är viktigt att vi tar emot avståndet i en double-variabel eftersom denna variant av metoden returnerar ett värde av typen double.

Övning 2

Testa den högra metoden int distanceOrigo().

Först måste den vänstra metoden tas bort från klassen Turtle. Enklast "tar vi bort" metoden genom att kommentera bort metodens kod.

Gör då så här: I klassen Turtle markera koden för metoden och högermusklicka och välj Comment Lines(s). Bild
Resultatet blir då att all kod i metoden kommer att inledas med teckenkombinationen // och därmed är metoden bortkommenterad. Bild

Koden kan senare lätt "avkommenteras" genom att markera koden och istället välja Uncomment Line(s).

Nu kan du kopiera och klistra in den högra metoden i klassen Turtle (t.ex. efter den bortkommenterade metoden) och kompilera.

Skapa en värld och en padda t1 i interaktionsrutan och anropa metoden så här:

int d = t1.distanceOrigo(); d Lagra avståndet i en variabel
och titta vad det är.
Denna gång tar vi emot värdet i en int-variabel eftersom denna variant av metoden returnerar ett värde av typen int.

Fler metoder i klassen Turtle

Metod Gör Exempel
int getXPos() Returnerar paddans x-koordinat. int x = t1.getXPos(); t1.getXPos() - t2.getXpos();
int getYPos() Returnerar paddans y-koordinat.
double distanceTo(int x, int y) Returnerar paddans avstånd till punkten (x, y).
int getDirection() Returnerar paddans riktning i grader där 0 är åt höger, 90 nedåt, 180 åt vänster, etc.
void setDirection(int direction) Ändrar paddans riktning till direction. t1.setDirection(90); t1.setDirection(0);
void moveTo(int x, int y) Flyttar paddan till angiven koordinat t1.moveTo(30, 50);

Observera:

Frågor och övningar

  1. Varför behöver metoden moveTo parametrar (x och y) men metoden getXPos inte behöver några parametrar?
  2. Båda datatyperna int och double förekommer både som returvärden och parametrar. Varför det?
  3. Skapa en värld w med två paddor t1 och t2. Flytta isär dem en bit.
    1. Testa metoderna som beskrivits ovan
    2. Vad händer om man gör de felaktiga (?) anropen w.getXPos() respektive t1.getHeight()? Slutsats?
    3. Går det att flytta en padda utanför världen?
    4. Skriv den sats (eller de satser) i interaktionsrutan som beräknar avståndet mellan paddorna!

Det finns i själva verket många fler metoder i klassen Turtle. Titta gärna på dokumentationen av Turtle som hör ihop med sköldpaddan.

if-satsen

För att kunna skriva kod som väljer mellan olika alternativ så behöver vi en så kallad villkorssats. Den vanligaste av dessa är if-satsen.
Läs minilektionerna om if-satsen och logiska uttryck!

Övningar på if-satsen

I dessa övningar skall du skriva metoder i klassen Turtle.
  1. Skriv en metod public boolean prison(double fence) som flyttar paddan till origo om den är mer än fence pixlar från origo. Använd metoden int distanceOrigo() som du redan har lagt in ovan. Metoden skall returnera true om sköldpaddan flyttats, annars false. Bekräfta att metoden fungerar, dvs att den returnerar true om de flyttar paddan, annars returnerar false.
  2. Skriv en metod int distClosestWall() i klassen Turtle som returnerar avståndet till den vägg som är närmast dvs det minsta av värden a, b, c och d i figuren nedan.
    world.png

    För att lösa detta problem behöver vi veta paddans position och världens storlek.

    Paddan vet ju sin egen position med hjälp av metoderna getXPos() och getYPos().

    Hur får paddan veta höjden och bredden på den värld som paddan är i?

    Paddan kan få en referens till den värld som den befinner sig i genom att anropa metoden getWorld() som finns i klassen Turtle.

    I klassen World finns metoderna getWidth() och getHeight() som returnerar världens bredd respektive höjd.

    Således kan koden

    World myWorld = this.getWorld(); int h = myWorld.getHeight(); int w = myWorld.getWidth();
    användas för att beräkna höjden och bredden på paddans värld.
    Observera att koden inte skapar något nytt värld-objekt! Variabeln myWorld är bara en referens till det egna värld-objektet.
    En mer erfaren programmerare hoppar vanligen över att föra in en egen variabel för världsreferensen utan skriver i stället ett så kallat "train wreck" (svenska?):
    int h = this.getWorld().getHeight(); int w = this.getWorld().getWidth();
    och utelämnar ofta även this framför getWorld-anropet.
  3. Skriv metoden void bounceWalls(int d) som flyttar paddan till världens mittpunkt om den är närmare en vägg en d punkter. Testa metoden mot alla fyra väggar!

while-satsen

För att kunna göra flera saker behöver man kunna skriva kod som upprepas. Sådan kod kallas för iterationer.
Läs minilektionen om while-satsen.

Övningar

  1. Skriv en metod drawCircle() som ritar (approximation till) en cirkel genom att med en while-iteration upprepade move(5) och turn(5). Vad ska man har för villkor i while-satsen?
  2. Skriv en metod void drawCircle(int radius) i klassen Turtle som låter paddan gå i (en approximation till) en cirkel med radien radius. Om paddan kommer närmare världens kanter än 10 punkter skall metoden avbrytas.
    circle.png

    Tips:

    1. Använd metoden void moveTo(int x, int y) som flyttar paddan till en absolut position.
    2. En punkterna på en cirkel med med mittpunkt i (xc, yc) och radie r ges av

      x = xc + r * cos(alfa)
      y = yc + r * sin(alfa)

      där alfa varierar mellan 0 och 2π. Låt while-satsen sköta variationen av alfa.
    3. Tänk på att Math.sin och Math.cos returnerar av värden av typ double medan moveTo har parametrar av typ int.

Felsökning

Att leta efter fel i program brukar kallas för avlusning eller, oftast, debugging. DrJava innehåller, liksom de flesta programmeringsmiljöer, ett verktyg för detta som brukar kallas för en debugger.

Prova gärna debuggern genom att gå igenom nedanstående minilektioner:


Gå till nästa lektion eller gå tillbaka

Valid CSS!