Asiaa static-sanasta

Staattisuudella (static) tarkoitetaan eri kielten välillä hieman eri asioita. Aihe on myöskin olio-ohjelmoinnin käsite, eikä valitettavasti kovin aloittelijaystävällinen sellainen, varsinkin kun Ohjelmointi 1 -kurssi ei varsinaisesti ole olio-ohjelmointikurssi. Alla on muutama esimerkki, jonka avulla avaamme staattisen muuttujan ja staattisen metodin käsitteitä C#:ssa. Jos tekstistä ei jää mitään muuta mieleen, niin toivottavasti edes seuraavat kaksi pääasiaa.

  1. Staattiseksi julistettu luokan jäsen (esimerkiksi muuttuja tai metodi) kuuluu tyyppiin itseensä, eikä mihinkään yksittäiseen olioinstanssiin.
  2. Staattinen jäsen jakaa arvonsa kaikkien kyseisestä luokasta tehtyjen olioinstanssien välillä.

Seuraavaksi oletamme, että olet tähän mennessä ymmärtänyt muuttujan käsitteen (M: 7. Muuttujat), ja harjoitellut muuttujien käyttöä omassa ohjelmassasi. Lisäksi oletamme, että ymmärrät, miten luokkia tehdään, ja kuinka luokasta tehdään olioinstanssi.

1. Staattinen metodi (aliohjelma)

Staattinen metodi luokan "yhteinen", eikä sitä voi kutsua olioinstanssin (viitemuuttujan) nimellä, vaan sitä kutsutaan luokan nimen avulla. Asian voisi ilmaista myös niin, että staattinen metodi on osa luokkaa (tyyppiä), mutta ei osa olioinstanssia.

Jos staattista metodia kutsutaan siitä luokasta, johon metodi on kirjoitettu, voi luokan nimen jättää kutsussa pois.

Tyypillistä staattiselle metodille on se, että kaikki sen tarvitsema tieto tulee parametreissa.

1.1 Esimerkki 1

# luokkia2

1.2 Esimerkki 2

Alla oleva koodi ei sen sijaan käänny...

# luokkia2olio

... vaan tuottaa virheen.

error CS0176: Member 'MunLuokka.TulostaTeksti()' cannot be accessed 
with an instance reference; qualify it with a type name instead

1.3 Esimerkki 3

Staattinen metodi ei voi muuttaa olioinstanssin jäsenen (tässä attribuutti a) arvoa. Alla oleva koodi ei käänny.

# staticmethod

... vaan tuottaa virheen

error CS0120: An object reference is required for the non-static field, 
method, or property 'MunLuokka.a'

Virhe tarkoittaa, että a-muuttujan arvoa ei voi muuttaa ilman olioinstanssia.

2. Attribuutti vs staattinen muuttuja

Staattinen muuttuja jakaa arvonsa kaikkien luokasta tehtyjen instanssien, eli olioiden, kanssa.

Toisin sanoen, kun samasta luokasta useita oliota, niin staattisen muuttujan arvo on sama kaikkien näiden olioiden välillä. Erityisesti, kun arvo muuttuu, niin muutos näkyy kaikissa olioissa, kuten vaikkapa jos haluat käyttää samaa korkoprosenttia kaikille ylläpitämäsi pankin tileille.

2.1 Huomautus

Käytännössä static-muuttujia on mielekästä käyttää vain tilanteissa, missä koko ohjelman suorituksen ajan on selvää, että kyseistä muuttujaa käytetään vain yhdessä merkityksessä. On tärkeää, että tällaisessa tilanteessa ei ole vaaraa, että muuttujan arvo muuttuu odottamattomasti.

Ohjelmointi 1 -kurssin yhteydessä oikeastaan ainoa hyväksyttävä käyttötapaus on sellainen, missä muuttujaa käytetään vakion tapaan silloin kun siitä ei kielen ominaisuuksien takia voida tehdä varsinaista vakiota. Esimerkiksi voi olla järkevää esitellä ohjelmaan yksi ainut taulukko, joka kuvaa vaikkapa kuukausien nimiä. Kun tämän taulukkoa ei silloin muuteta, on sen sisältö tavallaan vakio.

2.2 Esimerkki 1 (ei-staattinen, eli attribuutti)

Tässä esimerkissä OmaLuokka-luokassa on yksityinen, ei-staattinen muuttuja, jota kasvatetaan KasvataArvoa-metodin avulla. KasvataArvoa-metodi on myöskin ei-staattinen.

# luokka1attr

Käydään tämä esimerkki paloittain läpi. Dokumentaatiot on jätetty alla pois tilan säästämiseksi.

/// <summary>Luokka, jossa pääohjelma
/// sijaitsee.</summary>
public class OmaLuokka
{
    private int oma = 2;

    public int KasvataArvoa()
    {
        oma += 3;
        return oma;
    }
}

Yllä meillä on luokka, josta voidaan tehdä olioita (sitähän varten luokkia tehdään!)

Luokassa on yksityinen (private) muuttuja (luokassa esiteltyjä muuttujia kutsutaan englanniksi sanalla field, kurssilla on käytetty termiä attribuutti). Attribuuttia oma muutetaan olion KasvataArvoa-metodin avulla. Toisin sanoen, jokaisella OmaLuokka-luokasta tehdyllä oliolla on oma (erillinen) tila oma-muuttujalle, eikä kukaan yksikään toisen luokan olio voi muuttaa toisen olion omaa oma-attribuutin arvoa. Valitettavasti saman luokan olio kyllä pääsee käsiksi toisen saman luokan olion attribuutteihin.

KasvataArvoa-metodi on julistettu julkiseksi public-määreellä, joten se on kutsuttavissa siellä missä olio(instanssi) on käytettävissä. KasvataArvoa-metodin kutsuminen muuttaa aina oma-attribuutin arvoa. Varsinaisen arvon muutoksen tekee kukin olio itse.

public class Esimerkki
{
    public static void Main()
    {
        OmaLuokka olioviite = new OmaLuokka();
        Console.WriteLine(olioviite.KasvataArvoa());  // tulostaa 5
        OmaLuokka olioviite2 = new OmaLuokka();
        Console.WriteLine(olioviite2.KasvataArvoa()); // tulostaa 5
    }
}
# olioattribuutit

Pääohjelmassa (Main) tehdään juuri tekemästämme OmaLuokka-luokasta kaksi oliota, joihin viitataa olioviitemuuttujilla olioviite ja olioviite2. Tämän jälkeen kutsutaan olioiden KasvataArvoa-metodia. Metodin kutsumisen jälkeen tulostetaan paluuarvona tullut arvo (joka oli int-luku, kuten äsken näimme), ja huomaamme, että kummassakin tapauksessa tulostuu luku 5.

Vielä kertauksena: KasvataArvoa-metodin kutsuminen muuttaa kummankin olion kohdalla sen omaa, "henkilökohtaista" oma-attribuuttia, eikä muualta (esimerkiksi pääohjelmasta käsin) ole oikeutta mennä muuttamaan oma-attribuutin arvoa. Esimerkiksi tämä ei onnistuisi.

public class Esimerkki
{
    public static void Main()
    {
        OmaLuokka olioviite = new OmaLuokka();
        olioviite.oma = 5; // virhe!
    }
}

2.3 Esimerkki 2 (staattinen)

# luokka1attr2

Tämä ohjelma on lähes samanlainen, kuin Esimerkki 1:ssä. Pieni, mutta tärkeä ero on siinä, että yht-attribuutti on tällä kertaa merkitty staattiseksi. Tästä johtuen yht-muuttujan arvo on kaikille OmaLuokka-luokasta tehdyille olioille yhteinen. Mikä tahansa OmaLuokka-olio voi muuttaa yhteistä yht arvoa, ja muutos vaikuttaa kaikkiin kyseisen luokan olioihin. Tästä johtuen ensimmäinen tulostuslause pääohjelmassa tulostaa 5, ja seuraava 8. Staattinen muuttuja on hyvin likellä globaalia muuttujaa ja niiden käsittely ohjelmassa on hankalaa, koska on vaikea tietä kuka arvoja muuttaa milloinkin. Tästä johtuen staattisten muuttujien käyttö on varattu vain hyvin harvinaisia erikoistilanteita varten. Seuraavassa esimerkissä esitellään muutamia tällaisia erikoistilanteita.

# oliostattinen

2.4 Esimerkki 3 (staattinen)

Jypelin Game-luokassa on muutamia staattisia muuttujia. Näitä ovat muun muassa nimi, Exiting-tapahtuma ja kontrollit. Nämä ovat intuitiivisesti ajateltuna sellaisia asioita, jotka tapahtuvat joko kerran koko pelin eliniän aikana (esim. Exiting), tai sitten ovat koko pelin laajuisesti käytössä riippumatta siitä missä tilassa peli muuten on.

Esimerkiksi fyysisiä näppäimistöjä voi tietokoneessa olla vain yksi (no, voi oikeasti olla kiinnitettynä useampikin mutta ne kaikki painelevat samoja kirjaimia käyttöjärjestelmän näkökulmasta), joten on ihan luonnollista että kontrollit ovat yhteiset läpi pelin ajan.

2.5 Muistinvaraus

Oliolle varataan muisti sitä luotaessa, mutta staattisille muuttujille muisti varataan ennen olion luomista.

These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.