Metoder
Motivering
När program blir större finns det behov att kunna strukturera det bättre. Rätt användning av metoder gör din kod mycket läsbar, är mindre felbenägen och lättare att sköta. Metoder hjälper att strukturera programmet på samma sätt som du bryter ett större probelm i mindre.
Du har redan använd metoder från första lektionen utan att vara medveten om. rect(x, y, bred, höjd) är en metod, QuestionInt() är en metod och många fler. Men även tidigare när du har använd tex sin(double) på din miniräknare. Det de har gemensam att alla dessa metoder har (i regel) ett enda syfte, en enda uppgift. Med hjälp av fyra värden rita ett antal pixlar på skärmen, Gör ett pop-up fönster med en fråga eller levererar ett värde som har ett visst matematiskt samband med vinkeln i en triangel.
Kodexempel 1
Vi inför egna metoder för att våra program liknar mer sättet hur vi tänker, hur vi angripa ett problem och att öka läsbarheten. I första steget ta vi ett program till ett problem vi hade förr: Stapeldiagram
import java.util.Random;
//Variabler
int[] tal = new int[20]; // skapa lådan (=fält) 'tal' med 20 fack
Random rnd = new Random();
void setup(){
size(620,600);
int i = 0;
while( i < tal.length ){
int slmp = rnd.nextInt(200)+20; // generera slumptal 50 .... 450 och spara i slmp
tal[i] = slmp; // och spara i slmp
i++;
}
for(int j = 0; j < tal.length; j++){ //loopar genom fältet
int pos = 10+j*30;
rect(pos, 10, 20, tal[j] ); // och använda tal[i] för rektangelns höjd
}
}
Med metoder kan det ser ut så här. Vi skapa två metoder (fyllFaltetMedSlumptal(), RitaAllaTalSomstaplar() ) lite längre ner, anropa de i huvudprogrammet (under lektioner visas hur det kan läggas i andra filer):
import java.util.Random;
//Variabler
int[] tal = new int[20];
// Huvudprogram
void setup(){
size(620,600);
fyllFaltetMedSlumptal();
RitaAllaTalSomstaplar();
}
//======= egna metoder ====================================
void fyllFaltetMedSlumptal(){
Random rnd = new Random();
int i = 0;
while( i < tal.length ){
int slmp = rnd.nextInt(400)+50; // generera slumptal 50 .... 450 och spara i slmp
tal[i] = slmp; // och spara i slmp
i++;
}
} // end fyllFaltetMedSlumptal
void RitaAllaTalSomstaplar(){
for(int j = 0; j < tal.length; j++){ //loopar genom fältet
int pos = 10+j*30;
rect(pos, 10, 20, tal[j] ); // och använda tal[i] för rektangelns höjd
}
} // end RitaAllaTalSomstaplar
Läsbarheten i 'huvudprogrammet' är nu mycket bättre eftersom metodnamnen talar om för oss vad som är syfte med dem. Det visar också för den som läsa koden att problemet (Rita diagram med 20 slumptal) har delats upp i två mindre:
- Fyll fältet med innehåll
- Rita staplar beroende på fältet
Här används metoder på det enklaste sättet. Man sammanfattar kod med ett nytt namn och flytter den utanför. I exemplet har vi nu tre block setup, fyllFaltetMedSlumptal och RitaAllaTalSomstaplar. Först körs setup-blocket. I den anropas metoden fyllFaltetMedSlumptal. Programmet hoppar ner till rätt ställe och utför koden. Efter det är klar återvänder programmet till raden efter anropet och fortsätter, här med RitaAllaTalSomstaplar.
Syntax = skrivsätt
För att använda metoder krävs två saker: man måste deklarera metoden och sedan anropa. Man har flera sätt,vi börjar med det enklaste.
Deklaration:
Börja med void, sedan namnet följd av parentes. Det kallas för metodhuvud. Sedan kommer måsvingeparet. Mellan de sätts koden som ska utföras när metoden anropas. Det kallas metodkropp. Metoddeklaration från förra exemplet:
void fyllFaltetMedSlumptal(){
Random rnd = new Random();
int i = 0;
while( i < tal.length ){
int slmp = rnd.nextInt(200)+20; // generera slumptal 20 .... 220 och spara i slmp
tal[i] = slmp; // och spara i slmp
i++;
}
} // end fyllFaltetMedSlumptal
Anrop
Anrop sker från andra programdelar genom att skriva namnet följd av parenteser. Metodanrop från förra exemplet:
fyllFaltetMedSlumptal();
Än så har koden blivit mer läsbart. Men metoder är inte begränsad till ett enda anrop. Vi kunde ändra 'Huvudprogrammet' ändra så här:
// Huvudprogram
void setup(){
size(620,600);
fyllFaltetMedSlumptal();
RitaAllaTalSomstaplar();
translate(0,600); // flytta ner origo
scale(1,-1); // vända om y-axel
fyllFaltetMedSlumptal();
RitaAllaTalSomstaplar();
}
Metod med in-parameter
För att göra metoder mer flexibla kan man lägga till en eller flera in-parameter. Vi modfiera deklarationen. Jämför med förra version av fyllFaltetMedSlumptal:
void fyllFaltetMedSlumptal(int min, int max){ <--- Kolla! Nytt huvud
Random rnd = new Random();
int i = 0;
while( i < tal.length ){
int slmp = rnd.nextInt(max-min)+min; // generera slumptal min .... max och spara i slmp
tal[i] = slmp; // och spara i slmp
i++;
}
} // end fyllFaltetMedSlumptal
Men det innebär även en ändring i sättet att anropa metoden. I deklarationen skrivs void fyllFaltetMedSlumptal(int min, int max)
Och då krävs det att metoden anropas med två int-värden:
// Huvudprogram
void setup(){
size(620,600);
fyllFaltetMedSlumptal(20,800); <-------- Nytt sätt !!!
RitaAllaTalSomstaplar();
}
Laboration 1
Gör en metod innebär att definera metoden OCH anropa det med ett liten exempelhuvudprogram!
- Gör en metod som rita ett kvadrat på valfritt ställe. Metoddefinitionens första rad: void kvadrat(int x, int, y, int kantlangd)
Du kan börja så här:
// Huvudprogram
void setup(){
size(620,600);
kvadrat(50,100,200);
}
// och här ska komma definitionen/deklarationen för kvadrat:
- Utöka huvudprogrammet så att det blir fler kvadrater
- Ändra metoden att varje kvadrat får ett kryss i sig
- sätt en liten cirkel i mitten av kvadraten
-
Se till att cirkeln får röd färg. Men endast cirkeln! Exempel
-
skapa en metod som rita ett koordinatsystem på skärmen. Du kan använda
translate(x,y)
.
Programmet kan se ut så här:
// Huvudprogram
void setup(){
size(620,600);
ritaXYaxlar(300,400); // 300,400 är origo för axlarna
}
// och här ska komma definitionen/deklarationen för ritaXYaxlar:
Gör en metod som rita en enkel bil ( typ: två-tre rektanglar, två cirklar) på valfritt ställe på skärmen. In-parameter är x, y, och sedan kanske till och med - startnummer och färg. Rita så på ett enkelt sätt flera bilar på skärmen.
Metoder med ut-värden
Än så länge beskriver vi metoder som har ingen, ett eller flera in-parameter. Inte sällan vill man ha något ut av en metod. Alltså att det till exempel beräknas något som sedan ges tillbaka. Här ett lite exempel från fysiken:
void setup() {
size(600, 600);
textSize(36);
float temp = QuestionFloat("Temperatur i Celsius?");
float fah = Celsius2Fahrenheit(temp); <--- Anrop med ett värde
text(temp + " C⁰", 50, 50);
text(" blir " + fah + " F", 50, 100);
}
float Celsius2Fahrenheit(float celsius) <--- Innehållet av temp kopieras till celsius
{
float fahrenheit;
fahrenheit = celsius * 1.8 + 32;
return fahrenheit;
}
Observera två nyheter:
- I stället för void står nu float
- sista instruktion i metoden är return fahrenheit.
För att kunna få ett värde tillbaka måste vi specificera retur-värdets typ i det här fallet float. typen skrevs före metodnamnet. Det som returneras, här svar, måste då vara av typen double
Alla dessa varianter kan kombineras. Med eller utan returnvärde och inget, ett eller flera in-parameter. Det finns inga regler angående typer. Det kan vara vilken som helst in-typ och valfritt ut-typ:
void setup() {
int tal = 1337;
boolean b = isItPrime(tal);
if( b == true ) {
println(tal + " är ett primtal!");
} else {
println(tal + " är INGET primtal!");
}
}
boolean isItPrime(int n) {
boolean svar = true;
for (int i = 2; i < n; i++) {
if (n % i == 0) {
svar = false;
}
}
return svar;
}
Namngivning
Dessa regler gäller för namngivning av variabler och metoder:
- Skillnad mella stora och små bokstäver: getAntal, getantal, GETANTAL är tre olika variabler
- ett ord, så inte `antal elever` men `antal_elever` är OK.
- Tillåtna tecken: a - z, A-Z, 0 - 9, och _
- måste börja med bokstav eller _
- Good coding: Vi använder camelCase. variabelnamn börja men gemener, varje nytt ord `utan` mellanslag med versaler. Tex `antalElever, maxWidth, minBredd`
- I rekommendationer från Oracle ('Ägare' av Java) kan läsas: *Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized. Examples: run(); runFast(); getBackground();*
Laboration 2
Gör en metod innebär att definera metoden OCH anropa det med ett liten exempelhuvudprogram!
- Gör me metod som omvandla Fahrenheit till Celsius dvs det omvända till exempelt ovan.
- Gör en metod som ta emot två tal och returnera det största. Anropet kan ser ut så här:
float a = 3.142459, b = 13.37;
float maximum = Max(a,b);
text("Störst: " + maximum, 100,500);
-
Gör en metod som rita en cirkel på skärmen, beräkna och skriva till arean. Arean ska returneras. Anrop blir
float area = CirkelArea(200,100,50);
-
Använd metoden fyllFaltetMedSlumptal() från första exemplet för att fylla ett fält med slumptal. Skapa sedan en metod
Summa(int[] arr){ ...}
som beräkna och returnera summan.
Nyckelord för metoder
Viktiga begrepp
- metoddefinition: Hela koden som beskriver metoden
- metodhuvud: första raden av metoddefinition.
I den finns <returntyp> <metodnamn>(<typ> namn1, <typ> namn2, ...) - metodkropp: Själva koden för metoden.
- signatur : <metodnamn>(<typ> namn1, <typ> namn2, ...) samma som metodhuvud men utan returntyp. Sä länge metoder har olika signaturer kan de har samma namn.
Metoder och fält som in-parameter
In-parametrar för metoder är inte begränsade till int, float, double eller sträng. Det kan vara vad som helst, även fält. Ett exempel för konsollfönstret:
void setup() {
int[] f = {1, 2, 3, 4, 5};
snyggUtskrift(f);
}
void snyggUtskrift(int[] arr) {
for (int i = 0; i < arr.length; i++) {
print(arr[i] + "\t");
}
println();
}
Ett fält kan vara likaså ett returvärde för en metod:
double[] multiplerAvPI(int a) {
double[] arr = new double[a];
for (int i = 0; i < a; i++) {
arr[i] = (i+1) * PI;
}
return arr;
}
Laboration 3 - kopplar ihop fält och metoder
Hur skapas en metod?
du har en del av programmet som ska bli en metod. Med hjälp av dessa steg kan det översättas till en metod. Vi tar isItPrime från ovan som exempel. Först utan metod:
void setup() {
int tal = QuestionInt("Vilket tal ska testas?");
boolean arPrimtal = true;
for (int i = 2; i < tal; i++) {
if (tal % i == 0) {
arPrimtal = false;
}
}
if( arPrimtal ) {
text("Det är ett primtal", 20,100);
} else {
text("Det är INGET primtal", 20,100);
}
}
- En metod brukar lösa ett avgränsad problem som tex en beräkning eller lite mer komplex ritning. Avgränsa, ringa in vilka rader gör precis detta. Vi kalla det för metod koden. i det här fallet är det
boolean arPrimtal = true;
for (int i = 2; i < tal; i++) {
if (tal % i == 0) {
arPrimtal = false;
}
}
- Använda metoden värden som kommer från/bestäms i en tidigare del av programmet? De blir in-parameter av din metod. Bestäms ett värde i metodkoden som behövs senare i programmet? Det blir ditt returvärde. I vårt fall är det
tal
som är en in-parameter ocharPrimtal
som är ett returvärde. Nu kan vi bygga skalet för metoden:
boolean testPrimtal(int tal){
boolean arPrimtal = true;
return arPrimtal;
}
- Som namn valde vi
testaPrimtal
. Det ska vara självförklarande och ska hålla sig till regler (se ovan). Nu flyttar vi in koden och anropa metoden från huvudprogrammet
void setup() {
int tal = QuestionInt("Vilket tal ska testas?");
boolean arPrimtal = testPrimtal( tal ); //anrop
if( arPrimtal ) {
text("Det är ett primtal", 20,100);
} else {
text("Det är INGET primtal", 20,100);
}
}
// ===== metoddklaration ===================================
boolean testPrimtal(int tal){
boolean arPrimtal = true;
for (int i = 2; i < tal; i++) {
if (tal % i == 0) {
arPrimtal = false;
}
}
return arPrimtal;
}