Roolilista

Muuttujilla ja attribuuteilla on ohjelmissa eräitä tyypillisiä käyttötapoja, joita kutsutaan niiden rooleiksi. Esimerkiksi muuttujaa, jonka arvoa ei muuteta enää kertaakaan muuttujan alustamisen jälkeen, kutsutaan kiintoarvoksi. Rooleja ei pidä sekoittaa perustietotyyppeihin (Javassa esimerkiksi int, char, float jne.), vaan kyseessä on jaottelu, joka ilmaisee miten muuttuja tai attribuutti käyttäytyy kyseisessä ohjelmassa.

Seuraavassa kuvattavat yksitoista eri roolia riittävät kattamaan lähes kaikki yksinkertaisissa ohjelmissa esiintyvät muuttujat ja attribuutit. Useimmiten esiintyvät roolit ovat kiintoarvo, askeltaja ja tuoreimman säilyttäjä, jotka kattavat noin 70 % kaikista tapauksista. Toisaalta on huomattava, että kaikilla muuttujilla ja attribuuteilla ei välttämättä ole mitään alla esitellyistä rooleista.

Roolit, jotka on esitelty tarkemmin alla, ovat

Esimerkeissä olevan rivinumeroinnin tarkoitus on helpottaa riveihin viittaamista. Ohjelmien suorituksen kannalta rivinumeroinnilla ei ole mitään merkitystä, koska ne ovat muodoltaan Java-kommentteja.

Käyttäjän antama syöte luetaan esimerkeissä luokan UserInputReader avulla. Metodit UserInputReader.readFloat(), UserInputReader.readInt(), and UserInputReader.readChar() lukevat tyyppiä float, int ja char olevan arvon. Jos käyttäjä antaa virheellisen syötteen, esimerkiksi merkin metodille UserInputReader.readInt(), niin metodi UserInputReader tulostaa virheilmoituksen ja pyytää kelvollisen syötteen.

Icon for the role Kiintoarvo

Muuttujan rooli on kiintoarvo, jos sen arvoa ei muuteta ohjelman suorituksen aikana muuttujan alustamisen jälkeen. Esimerkkiluokka mallintaa pankkitilin tiedot. Attribuutti tiliNumero on kiintoarvo. Se saa ohjelman suorituksen aikana yhden kerran arvon (rivillä 7), joka ei sen jälkeen muutu. Kiintoarvoa voidaan käyttää ohjelman eri kohdissa - esimerkissä rivillä 10.

/*  1 */ public class PankkiTili {
/*  2 */
/*  3 */    String tiliNumero;
/*  4 */    float saldo=0;
/*  5 */
/*  6 */    public PankkiTili (String nro) {
/*  7 */       tiliNumero = nro;
/*  8 */    }
/*  9 */
/* 10 */    public String annaTiliNumero () { return tiliNumero; }
/* 11 */
/* 12 */    public float tiliTapahtuma (float muutos) {
/* 13 */       saldo += muutos;
/* 14 */       return saldo;
/* 15 */    }
/* 16 */ }

(Attribuutti saldo on kokooja.)

Icon for the role Askeltaja

Askeltaja käy läpi arvoja jollain systemaattisella tavalla. Alla on esimerkki silmukkarakenteesta, jossa käytetään muuttujaa kertoja askeltajana. Esimerkkiohjelma tulostaa kolmosen kertotaulun askeltajan käydessä läpi arvot yhdestä kymmeneen.

/* 1 */ public class Kertotaulu {
/* 2 */    public static void main(String[] args) {
/* 3 */    int kertoja;
/* 4 */    for (kertoja = 1; kertoja <= 10; kertoja++)
/* 5 */       System.out.println(kertoja + " * 3 = " + kertoja * 3);
/* 6 */    }
/* 7 */ }
Askeltajaa voidaan käyttää myös esimerkiksi lukumäärän laskemiseen ja taulukon indeksien läpikäymiseen.

Icon for the role Tuoreimman säilyttäjä

Tuoreimman säilyttäjän arvo on viimeisin jostakin tietystä joukosta läpikäyty arvo tai yksinkertaisesti vain arvo, joka on syötetty viimeksi. Esimerkkiohjelma pyytää käyttäjältä syötettä toistuvasti (rivillä 7) kunnes syöte on kelvollinen. Tässä ohjelmassa muuttuja s on tuoreimman säilyttäjä, koska siitä löytyy kulloinkin viimeksi syötetty arvo.

/*  1 */ public class NelionAla {
/*  2 */
/*  3 */    public static void main(String[] args) { 
/*  4 */       float s = 0f;
/*  5 */       while (s <= 0) {
/*  6 */           System.out.print("Anna neliön sivu: ");
/*  7 */           s = UserInputReader.readFloat();
/*  8 */       }
/*  9 */       System.out.println("Neliön ala on " + s * s);
/* 10 */    }
/* 11 */ }

Icon for the role Sopivimman säilyttäjä

Sopivimman säilyttäjän arvo on "paras" tai jollain muulla tavoin halutuin siihen asti läpikäydyistä arvoista. Arvojen paremmuuden mittamisessa ei ole mitään rajoituksia: halutuin voi tarkoittaa esimerkiksi pienintä tai suurinta lukua tai sellaista lukua, joka on lähinnä jotain tiettyä arvoa.

Esimerkkiluokka selvittää, mikä tilastoitavista lämpötiloista on suurin. Attribuutti maksimiLampo on sopivimman säilyttäjä, koska siihen sijoitetaan (rivillä 15) uusin lämpötila, mikäli se on suurempi kuin suurin tähän mennessä läpikäydyistä.

/*  1 */ import java.util.Vector;
/*  2 */
/*  3 */ public class LampoTilasto {
/*  4 */
/*  5 */    Vector lampotilat;
/*  6 */    int maksimiLampo;
/*  7 */
/*  8 */    public LampoTilasto () {
/*  9 */       lampotilat = new Vector();
/* 10 */       maksimiLampo = -99999;
/* 11 */    }
/* 12 */
/* 13 */    public void lisaaTieto (int lampotila) {
/* 14 */       lampotilat.add(new Integer(lampotila));
/* 15 */       if (lampotila > maksimiLampo) maksimiLampo = lampotila;
/* 16 */    }
/* 17 */ }

(Attribuutti lampotilat on säiliö.)

Icon for the role Kokooja

Kokoojan arvo kerääntyy kaikista siihen mennessä läpikäydyistä arvoista. Esimerkkiohjelma ottaa vastaan yksi kerrallaan käyttäjän syöttämiä kokonaislukuja, kunnes käyttäjä syöttää luvun -999, jonka jälkeen ohjelma laskee syötteiden keskiarvon. Muuttuja summa on kokooja: siihen kootaan (rivillä 9) syötteiden kokonaissummaa.

/*  1 */ public class Keskiarvo {
/*  2 */
/*  3 */    public static void main(String[] argv) {
/*  4 */       int lkm=0;
/*  5 */       float summa=0, luku=0;
/*  6 */       while (luku != -999) {
/*  7 */          System.out.print("Anna luku, -999 lopettaa: ");
/*  8 */          luku = UserInputReader.readFloat();
/*  9 */          if (luku != -999) {summa += luku; lkm++; }
/* 10 */       }
/* 11 */       if (lkm>0) System.out.println("Keskiarvo on " + summa / lkm);
/* 12 */    }
/* 13 */ }

(Muuttuja lkm on askeltaja ja luku on tuoreimman säilyttäjä.)

Icon for the role Seuraaja

Seuraaja saa aina arvokseen jonkin tietyn toisen muuttujan tai attribuutin vanhan arvon. Esimerkkiohjelma pyytää käyttäjältä 12 kokonaislukua ja kertoo lopuksi, mikä oli suurin kahden perättäisen syötetyn luvun ero. Muuttuja edellinen on seuraaja: se seuraa muuttujaa nykyinen (rivillä 9).

/*  1 */ public class SuurinEro {
/*  2 */   
/*  3 */    public static void main(String[] args) {  
/*  4 */       int kuukausi, nykyinen, edellinen, suurinEro;
/*  5 */       System.out.print("Anna 1. arvo: "); edellinen = UserInputReader.readInt();
/*  6 */       System.out.print("Anna 2. arvo: "); nykyinen = UserInputReader.readInt();
/*  7 */       suurinEro = nykyinen - edellinen;
/*  8 */       for (kuukausi = 3; kuukausi <= 12; kuukausi++) {
/*  9 */          edellinen = nykyinen;
/* 10 */          System.out.print("Anna " + kuukausi + ". arvo: ");
/* 11 */          nykyinen = UserInputReader.readInt();
/* 12 */          if (nykyinen - edellinen > suurinEro)
/* 13 */             suurinEro = nykyinen - edellinen;
/* 14 */       }
/* 15 */       System.out.println("Suurin ero oli " + suurinEro);
/* 16 */    }  
/* 17 */ }

(Muuttuja kuukausi on askeltaja, nykyinen on tuoreimman säilyttäjä ja suurinEro on sopivimman säilyttäjä.)

Seuraajia käytetään paljon linkitettyjen tietorakenteiden yhteydessä osoittamaan käsiteltävää alkiota edeltänyttä alkiota.

Icon for the role Yksisuuntainen lippu

Yksisuuntaisella lipulla on kaksi mahdollista arvoa eikä ei saa enää alkuperäistä arvoaan sen jälkeen, kun se on kerran muuttunut. Esimerkkiluokka selvittää, esiintyykö tilastoitavien lämpötilojen joukossa negatiivista lukua. Yksisuuntainen lippu ollutPakkasta tarkkailee (rivillä 15) esiintyykö tilastoitavien lämpötilojen joukossa yhtään negatiivista arvoa ja jos yksikin negatiivinen arvo löytyy, ei muuttuja enää palaa arvoon false.

/*  1 */ import java.util.Vector;
/*  2 */
/*  3 */ public class LampoTilasto2 {
/*  4 */
/*  5 */    Vector lampotilat;
/*  6 */    boolean ollutPakkasta;
/*  7 */
/*  8 */    public LampoTilasto2 () {
/*  9 */       lampotilat = new Vector();
/* 10 */       ollutPakkasta = false;
/* 11 */    } 
/* 12 */
/* 13 */    public void lisaaTieto (int lampotila) {
/* 14 */       lampotilat.add(new Integer(lampotila));
/* 15 */       if (lampotila < 0) ollutPakkasta = true; 
/* 16 */    } 
/* 17 */ }

(Attribuutti lampotilat on säiliö.)

Yksisuuntaista lippua voidaan käyttää myös esimerkiksi tarkkailemaan virheen esiintymistä syöttötiedoissa, jotta ohjelma huomaisi pyytää syötteitä uudelleen.

Icon for the role Tilapäissäilö

Tilapäissäilön arvoa tarvitaan aina vain hyvin lyhyen ajan. Esimerkkiohjelma mallintaa tuotteen, jolla on kiinteä veroton hinta, mutta jonka veroprosenttia voidaan vaihtaa. Vero lasketaan tilapäissäilöön vero (rivillä 11), jota käytetään vain kahdella seuraavalla rivillä heti laskentansa jälkeen.

/*  1 */ public class Tuote {
/*  2 */ 
/*  3 */    float verotonHinta, verollinenHinta;
/*  4 */
/*  5 */    public Tuote (float hinta) { 
/*  6 */        verotonHinta = hinta;
/*  7 */    }
/*  8 */
/*  9 */    public float asetaVero (float veroProsentti) { 
/* 10 */       float vero;
/* 11 */       vero = veroProsentti * verotonHinta / 100;
/* 12 */       verollinenHinta = verotonHinta + vero;
/* 13 */       return vero;
/* 14 */    }
/* 15 */ }

(Attribuutti verotonHinta on kiintoarvo ja verollinenHinta on tuoreimman säilyttäjä.)

Tilapäissäilöä käytetään tyypillisesti ohjelman tehostamiseen (suorittamalla laskutoimitus, jonka tulosta tarvitaan useasti, vain kertaalleen) tai ohjelman selventämiseen (laskemalla tulos omaan muuttujaansa vaikka tämä ei ole välttämättä tarpeen). Tilapäissäilöä käytetään usein myös järjestelijän kahden alkion keskinäisen paikan vaihtamiseen.

Icon for the role Järjestelijä

Järjestelijä on tietorakenne, jota käytetään siinä olevien tietojen uudelleen järjestämiseen sen jälkeen, kun se on ensin alustettu joillakin arvoilla. Esimerkkiohjelma pyytää käyttäjältä kymmenen merkkiä taulukkona toteutettuun järjestelijään merkki, kääntää niiden järjestyksen taulukossa ja lopuksi tulostaa merkit tässä käännetyssä järjestyksessä.

/*  1 */ public class Kaanna {
/*  2 */    
/*  3 */    public static void main(String[] args) {
/*  4 */       char[] merkki = new char[10];
/*  5 */       char tmp; int i; 
/*  6 */       System.out.print("Anna kymmenen kirjainta: ");
/*  7 */       for (i = 0; i < 10; i++) merkki[i] = UserInputReader.readChar();
/*  8 */       for (i = 0; i < 5; i++) {
/*  9 */          tmp = merkki[i];
/* 10 */          merkki[i] = merkki[9-i];
/* 11 */          merkki[9-i] = tmp;
/* 12 */       }
/* 13 */       for (i = 0; i < 10; i++) System.out.print(merkki[i]);
/* 14 */       System.out.println();
/* 15 */    }
/* 16 */ }

(Muuttuja tmp on tilapäissäilö ja i on askeltaja.)

Järjestelijää voidaan käyttää lajitteluun tai muuhun uudelleenjärjestelyyn.

Icon for the role Säiliö

Säiliö on tietorakenne, johon voidaan lisätä ja josta voidaan poistaa tietoja. Esimerkkiohjelma toteuttaa pinon, jossa poistettava on kulloinkin viimeksi lisätty kokonaisluku. Tähän luokkaan kuuluvat oliot (esimerkiksi attribuutti minunPinoni rivillä 28) ovat säiliöitä: niihin voidaan lisätä alkioita (metodilla lisaa riveillä 8-15) ja poistaa alkioita (metodilla poista riveillä 17-24).

/*  1 */ public class Pino {
/*  2 */ 
/*  3 */    private int sisalto;
/*  4 */    private Pino seur; 
/*  5 */ 
/*  6 */    public Pino() { this.seur = null; } 
/*  7 */ 
/*  8 */    public void lisaa (int lisattava) {
/*  9 */       Pino uusi;
/* 10 */        
/* 11 */       uusi = new Pino(); 
/* 12 */       uusi.sisalto = lisattava;
/* 13 */       uusi.seur = this.seur;
/* 14 */       this.seur = uusi; 
/* 15 */    }
/* 16 */ 
/* 17 */    public int poista () {
/* 18 */       int poistettava = 0;
/* 19 */       if (this.seur != null) { 
/* 20 */          poistettava = this.seur.sisalto;
/* 21 */          this.seur = this.seur.seur;
/* 22 */       }
/* 23 */       return poistettava;
/* 24 */    }
/* 25 */ }
/* 26 */ 
/* 27 */ class PinoTesti {
/* 28 */    Pino minunPinoni = new Pino();
/* 29 */    ...
/* 30 */ }

(Attribuutti sisalto on kiintoarvo, seur on oliossa minunPinoni tuoreimman säilyttäjä ja muissa oliossa kiintoarvo, muuttuja uusi on tilapäissäilö ja poistettava on tilapäissäilö.)

Icon for the role Kulkija

Kulkija käy läpi jotain tietorakennetta. Esimerkkiohjelmassa on ylläolevaan Pino-luokkaan lisätty metodi koko, joka palauttaa pinon sisältämien alkioiden lukumäärän. Muuttuja p on kulkija: se käy läpi pinon kaikki alkiot (rivillä 16).

/*  1 */ public class Pino {
/*  2 */ 
/*  3 */    private int sisalto;
/*  4 */    private Pino seur; 
/*  5 */ 
/*  6 */    public Pino() { this.seur = null; } 
/*  7 */    public void lisaa (int lisattava) { ... }
/*  8 */    public int poista () { ... }
/*  9 */
/* 10 */    public int koko () {
/* 11 */       int koko = 0;
/* 12 */       Pino p = this.seur;
/* 13 */
/* 14 */       while (p != null) {
/* 15 */          koko++;
/* 16 */          p = p.seur;
/* 17 */       }
/* 18 */       return koko;
/* 19 */    }
/* 20 */
/* 21 */ }

(Muuttuja koko on askeltaja.)


Päivitetty viimeksi: 24.1.2006

saja.fi@gmail.com
Petri.Gerdt@UEF.Fi