wiki:MuuttujienNakyvyys
Last modified 8 months ago Last modified on 2016-10-30 11:23:24

Dokumentti siirretty TIMiin


Luentomonisteen täydennykset » Muuttujien näkyvyys

Muuttujien näkyvyydellä (eng. scope) tarkoitetaan sitä, missä tilanteessa muuttuja on käytettävissä. Jos muuttuja "on näkyvissä" (in scope), niin voimme koodissamme kyseisessä kohdassa käyttää muuttujaa. Vastaavasti, jos muuttuja "ei ole näkyvissä" (not in scope), emme pääse käsiksi muuttujaan ja sen sisältämään arvoon kyseisessä paikassa. Konkreettisia esimerkkejä on esitetty alla.

Pääasiassa muuttujat ovat näkyvissä siinä lohkossa, jossa ne on esitelty. Eli oikeastaan kaikki alla olevat "säännöt" seuraavat tätä soveltaen. Muuttujat ovat olemassa niin kauan kuin lohkosta ei olla poistuttu Aliohjelmakutsun aikana lohkosta ei ole poistuttu, siihenhän tullaan vielä takaisinkin.

Katso esimerkkiohjelmaa MuuttujienNakyvyys.cs

1. Pääohjelman muuttujat

Pääohjelmassa (tai missä tahansa muussakin aliohjelmassa) esitellyt muuttujat näkyvät vain oman esittelynsä lohkon (alkaa aaltosululla { ja päättyy aaltosululla }) sisällä esittelynsä jälkeen:

public static void Main(String[] args)
{
    int luku = 9;  
    double d = 5.5;
    int[] luvut = { 1, 2, 3 }; 
    Muuta(luvut, 2, luku);
 ...
}

Edellä luku ja d ovat nähtävissä ja muutettavissa vain pääohjelmassa (paitsi jos viedään C#:issa out-parametrina). Muuttuja luvut on periaatteessa käytettävissä (ja muutettavissa) vain pääohjelmassa.

Kuitenkin, koska taulukkokin on olio C#:issa, se viedään aliohjelmalle (kuten tässä Muuta-aliohjelmalle) viitteenä. Viitteen kautta aliohjelma voi muuttaa pääohjelman taulukon sisältöä, koska Muuta-aliohjelman parametrimuuttuja viittaa samaan taulukko-olioon, kuin pääohjelman muuttuja.

Kaikki edellä esitellyt kolme muuttujaa elävät pääohjelman loppusulkuun } saakka. Muuttujan luku arvo kopioidaan aliohjelman vastinmuuttujaan. Aliohjelma ei mitenkään "näe" pääohjelman muuttujaa, vaan aliohjelma saa tiedokseen sille välitetyn arvon.

args-taulukko on pääohjelman parametrimuuttuja (ks. alla), joka viittaa pääohjelman kutsussa käytettyihin merkkijonoihin.

2. Aliohjelman muuttujat

Aliohjelmalle tärkeimmät muuttujat tulevat parametrin välityksen kautta. Toki aliohjelmaan tarvitaan usein omia apumuuttujia ongelman selvittämiseksi.

2.1 Aliohjelman parametrimuuttujat

Aliohjelmakutsussa aliohjelman parametrimuuttujiin kopioidaan kutsussa olevien lausekkeiden arvot siinä järjestyksessä kuin ne kutsussa ovat. Pitää muistaa että esimerkiksi taulukkokin on arvo, eli sen taulukon viitearvo, jossa välitettävä taulukko "asuu".

public static void Muuta(int[] luvut, int paikka, int luku)
{
    luvut[paikka] = luku; // viitteen ansiosta pääohjelman taulukko muuttui
    paikka--;             // ei vaikuta pääohjelmaan
    int uusiarvo;         // aliohjelman lokaali muuttuja
    uusiarvo = luku +3;
    luvut[paikka] = uusiarvo; // muuttaa pääohjelman taulukkoa
    luku = 12;            // ei vaikuta pääohjelmaan 
}

Esimerkissä parametrimuuttujan (taulukkoviitteen) nimi on sama luvut kuin pääohjelmassakin, mutta nimi voisi olla mikä tahansa muukin. Oleellista on, että kutsussa aliohjelman vastaavassa paikassa olevaan viitemuuttujaan sijoitetaan sama viite kuin kutsuvassakin ohjelmassa.

paikka on myös parametrimuuttuja, samoin kuin luku. Vaikka muuttujaan luku sijoitettaisiin jotakin, se ei vaikuta kutsuvaan ohjelmaan, koska luku on oma muuttuja aliohjelmassa ja on olemassa vain siihen saakka kun kunnes tullaan aliohjelman loppusulkuun }.

Parametrimuuttujien muuttamista ei yleisesti pidetä hyvänä tyylinä. Jos parametrimuuttujia pitää muuttaa, parempi on tehdä niistä lokaali kopio ja muuttaa sitä, näin aliohjelman lopussa parametreilla on samat arvon kuin aliohjelmaan tultaessakin.

2.2 Aliohjelman lokaalit muuttujat

Aliohjelma voi tarvita myös lokaaleja apumuuttujia "ongelman" ratkaisemiseen:

paikka--;             // ei vaikuta pääohjelmaan
int uusiarvo;         // aliohjelman lokaali muuttuja
uusiarvo = luku + 3;
luvut[paikka] = uusiarvo; // muuttaa pääohjelman taulukkoa

Tässä apumuuttuja uusiarvo on näkyvissä aliohjelmassa esittelyrivinsä jälkeen, mutta lakkaa olemasta kun tullaan aliohjelman loppusulkuun }. Tähän muuttujaan tehdyt muutokset (vaikka jossakin olisi samanniminenkin muuttuja) eivät millään tavalla vaikuta mihinkään muuhun paikkaan kuin tähän muuttujaan. Pääohjelma tai kukaan muukaan ei pääse käsiksi tähän muuttujaan millään tavalla (paitsi tässä tapauksessa kun tuo arvo riippuu parametrina tuodun luku-muuttujan arvosta).

3. Omassa lohkossa esitellyt muuttujat

Joskus voidaan esitellä apulohko, jonka sisällä on omat muuttujat, joihin pääsee käsiksi vain lohkon sisällä. Esimerkiksi malliohjelman pääohjelmassa voisi olla

Muuta(luvut, 2, luku);
{                          // apulohko, jossa omia muuttujia
    int uusi = 3;          // muuttuja joka näkyy vain tässä lohkossa
    Console.WriteLine(uusi);
}                          // nyt uusi-muuttuja lakkaa olemasta
// Nyt muuttujaa uusi ei ole olemassakaan

Nyt muuttuja uusi on olemassa vain sulkujen { ja } välisen ajan ja sulkujen ulkopuolelta niihin ei pääse käsiksi. Tehty lohko ei mitenkään liity aliohjelman Muuta kutsuun, vaikka visuaalisesti voisi siltä näyttääkin. Useimmiten tätä erillisen lohkon ominaisuutta käytetään ehtolauseiden tai silmukoiden sisällä olevissa lohkoissa.

4. Silmukan muuttujat

Silmukoissa on yleensä silmukkamuuttuja, jonka täytyy muuttua silmukan aikana, jotta silmukka ei ole ikuinen. Lisäksi ongelman selvittämiseksi silmukassa voi olla tarvittavia apumuuttujia.

int luku = 9;
...
// Täytetään taulukkoa
int edellinen = 0;
for (int i = 0; i < luvut.Length; i++)
{
    int nyt = luvut[i];     // on olemassa silmukan sisällä
    int iso = 3 * nyt;      // on olemassa silmukan sisällä
    luvut[i] += iso; 
    edellinen = nyt + luku; // silmukan ulkopuolella määritelty muuttuja
}

4.1 Silmukkamuuttujat

Edellisessä esimerkissä muuttuja i on olemassa ja käytettävissä koko silmukan ajan, mutta ei enää silmukan loppusulun } jälkeen.

4.2 Silmukan ulkopuolella esitellyt muuttujat

luku ja edellinen ovat olemassa ennen silmukkaa, sen aikana ja sen jälkeen mikäli i:n arvoa tarvittaisiin silmukan jälkeenkin, pitäisi se esitellä silmukan ulkopuolella:

int i;
for (i = 0; i < luvut.Length; i++)
{
   ...
}
/// Nyt i on täällä vielä olemassa ja sen arvo voidaan esim katsoa

Tämän ulkopuolella esitellylle silmukkamuuttujan hinta on se, että ei voida enää käyttää samaa nimeä samassa lohkossa olevalle toiselle silmukkamuuttujalle. Jos silmukkamuuttujat esitellään for-lauseen sisällä, voidaan samaa nimeä käyttää seuraavassakin for-silmukassa.

for-silmukan ulkopuolella esiteltyä silmukkamuuttujaa tarvitaan useimmiten silloin, kun silmukan suoritus katkaistaan break-lauseella ja silmukan jälkeen pitäisi tietää, mihin indeksiin saakka silmukkaa suoritettiin.

4.2 Silmukan sisällä esitellyt muuttujat

Lohkon sisällä määritellyt muuttujat nyt ja iso ovat olemassa vain lohkonsa sisällä ja niiden mahdollinen arvo häviää jokaisen silmukan kierroksen päätteeksi. Lopputulos on aivan vastaava, vaikka muuttujat esiteltäisiin silmukkalohkon ulkopuolella:

int luku = 9;
...
// Täytetään taulukkoa
int edellinen = 0;
int nyt;
int iso;
for (int i = 0; i < luvut.Length; i++)
{
    nyt = luvut[i];   
    iso = 3 * nyt;    
    luvut[i] += iso; 
    edellinen = nyt + luku; 
}

Haittana ulkopuolella esittelylle on se, että nyt samoja nimiä ei voi käyttää toisessa lohkossa.

5. Attribuutit

Olioiden sisällä voi olla omia muuttujia, joita nimitetään attribuuteiksi. Kirjallisuudessa käytetään myös nimeä kenttä (eng. field). Attribuutit kannattaa lähes poikkeuksetta esitellä private-määreellä, jolloin kukaan ulkopuolinen ei pääse niihin käsiksi. Attribuutit ovat olemassa koko olion elinkaaren ajan, ja jokainen olion (luokkaan kirjoitettu) metodi (siis ei-static aliohjelma) pääsee niihin käsiksi. Attribuuttien runsas käyttö on kuitenkin sekin vaarallista luokan koon kasvaessa. Attribuutteja pitääkin osata käyttää varoen ja taitavasti, ja mielellään vain harvoissa erityistilanteissa.

Metodien (olion omien aliohjelmien) sisällä esitellyt muuttujat ja metodien parametrimuuttujat käyttäytyvät kuten aikaisemmissa kohdissa on kuvattu.

6. Globaalit muuttujat

Muuttuja voidaan esitellä myös kaikkien aliohjelmien ulkopuolelle ja tällöin muuttuja on globaali. Tällaista esittelyä tulee KAIKIN KEINOIN VÄLTTÄÄ. Tuloksena on vain iso tukku ONGELMIA. Kaikkein hankalimmin paikannettavat virheet liittyvät globaaleihin muuttujiin.

Linkkejä