csharp.aspone.cz csharp.aspone.cz

Klíčové slovo static

Pokud uvedu klíčové slovo static, musím daný člen volat přímo na úrovni třídy, nikoliv z instance typu.
Statické členy jsou prvky, u nichž bylo záměrem, aby byly hned po ruce tak, že nebude kvůli nim nutné vytvářet instanci typu.


Statické metody

Statické členy mohou operovat pouze se statickými členy třídy. Pokusíte-li se uvnitř statické metody použít nějaké členy, které nejsou statické, obdržíme chybu při kompilaci.

Data která nejsou statická se musí volat na úrovni objektu.


Statická data

Můžeme také definovat statická data. Pokud třída definuje data, která nejsou statická, bude si každý objekt daného typu udržovat privátní kopii těchto dat. Statická data se alokují pouze jednou a sdílejí všechny instance objektů téhož typu. Statické metody mohou operovat pouze se statickými daty. Metoda, která není statická může pracovat se statickými i nestatickými daty. Proto ve výše uvedeném příkladě je členská proměnná Random statická.


Statické konstruktory

Pomocí konstruktorů se nastavují hodnoty dat typu v okamžiku, kdy se konstruují. Kdybychom jsme chtěli přiřadit hodnotu nějakému prvku statických dat uvnitř konstruktoru úrovně instance, hodnota se znovu obnoví na původní pokaždé, když vytvoříme nový objekt. J

Statické konstruktory mají jistá pravidla a to:
* Daná třída může definovat pouze jediný statický konstruktor
* Statický konstruktor se vykoná přesně jednou, bez ohledu na to, kolik objektů daného typu se vytvoří.
* Statický konstruktor nepřebírá žádný modifikátor přístupu a nemůže přebírat žádné parametry
* Statický konstruktor se vykoná před všemi konstruktory úrovně instance
* Runtime vyvolá statický konstruktor v okamžiku, kdy vytvoří instanci třídy, nebo předtím, než přistoupí k prvnímu statickému členu, který je vyvolán volajícím.



Statické třídy

Když je třída definována jako statická, nedají se vytvářet její instance klíčovým slovem new, a může obsahovat pouze statické členy a statické členské proměnné. Pokud se vytvoří třída, která neobsahuje nic jiného, než statické členy nebo konstantní data, nemusí se třída předem alokovat.

Statická data

Tento příklad jsem opět nalezl v knize C# a .NET 2.0 profesionálně, trochu jsem ho upravil. Je dobré se nad ním zamyslet.
Jsou zde vlastně 2 a 2 metody, jeden pár je statický a druhý normální. Oba dva druhy inicializují nebo vrací proměnnou currInterestRate.
Ještě jednou připomínám, že statická metoda, může pracovat pouze se statickými daty.
Třída SavinsAccount - zde je proměnná double currbalance a statická proměnná currInterestRate inicializovaná hodnotou 0.05. Jestli jsem to pochopil dobře, tak statická data sdílejí všechny instance definující třídy. Dále SavingsAccount, kde při použití konstruktoru se uloží hodnota do currBalance. Tato metoda je zajímavá pouze tím, že vlastně můžu vytvářet více konstruktorů, ale můžu určit více parametrů typu double a tak jich můžu vytvořit habaděj aaaaa hodnota se vždy jen uloží a nevyužije :D. Tak tedy každý objekt typu SavingsAccount si udržuje kopii proměnné currbalance.
Je zde statická metoda SetInterestRate, ta inicializuje hodnotu currInterestRate.
Je zde metoda GetInterestRate, tuto metodu zavolám a vrátí mi jen hodntotu proměnné currInterestRate.
Další metoda SetInterestRateObj inicializuje proměnnou currInterestRate, akorát není statická.
A opět další metoda GetInterestRateObj, zde vrací hodntotu proměnné currInterestRate a také není statická.
V třídě hlavniProgram je metoda Main v ní 3 konstruktory s1, s2, s3 s určitými nevýznamnými parametry. Dále jsem pomocí Console.WriteLine vypsal demonstrativně hodnotu currInterestRate 2x normálně a pak jsem ji vypsal přes statickou metedu GetInterestRate a ta se volá na úrovni objektu.
Dále jsme změnili hodnotu currInterestRate. Vytvořili konstruktor s3 a vypsali pomocí statické metody GetInterestRate.
O5 jsme na úrovni objektu změnili hodnotu currInterestRate a vypsali pomocí konstruktoru.

using System;                                                         

class SavingsAccount
{
    public double currBalance;
    public static double currInterestRate = 0.05;

    public SavingsAccount(double balance)
    { currBalance = balance;  }

    public static void SetInterestRate(double newRate) //S.T.A.T.I.C.K.A
    { currInterestRate = newRate; }

    public static double GetInterestRate()  //S.T.A.T.I.C.K.A
    { return currInterestRate;  }

    public void SetInterestRateObj(double newRate)
    { currInterestRate = newRate; }

    public double GetInterestRateObj()
    { return currInterestRate; }
}


class hlavniProgram
{

static void Main(string[] args)
  {
    SavingsAccount s1 = new SavingsAccount(9);
    SavingsAccount s2 = new SavingsAccount(109);

    Console.WriteLine("Urokova mira je : {0}", s1.GetInterestRateObj());
    Console.WriteLine("Urokova mira je : {0}", s2.GetInterestRateObj());   
    Console.WriteLine("Urokova mira je : {0}", SavingsAccount.GetInterestRate());

    s2.SetInterestRateObj(0.08);

    SavingsAccount s3 = new SavingsAccount(10000.75);
  
    Console.WriteLine("Urokova mira je : {0}", SavingsAccount.GetInterestRate());
    
    SavingsAccount.SetInterestRate(0.934);
    Console.WriteLine("Urokova mira je : {0}", s3.GetInterestRateObj());
  }
}

Statické metody

Zde je příklad na statické metody. Vlastně díky statické metodě ji nemusím volat na úrovni objektu.
Zde je třída Teenager, všimněte si, že v metodě Main volám metodu Complain, jelikož je statické, nemusím ji volat na úrovni objektu. Je zde metoda Random, díky ní získáme náhodné číslo, ještě ji moc nerozumím. Jasné je, že v mětodě Complain je použito pole řetězců. Řetězce jsou zadané mezi uvozovky. Metoda vrací řetězec a díky metodě GetRandomNumber se zvolí jedna z nich a to náhodně. V mětodě Main se pak vypsalo 10x náhodný řetězec z metody Complain ve třídě Teenager.

using System;

class Teenager
{
 private static Random r = new Random();

 private static int GetRandomNumber(short upperLimit)
 {
  return r.Next(upperLimit);
 }
    public static string Complain()
    {
      string[] messages = new String[5] { "Opravdu musim?", "On si zacal!" 
      +" Jsem strasne unavenej...", "Nenavidim skolu", "Ses uplne vedle."};
      return messages[GetRandomNumber(5)];
    }
}

class hlavniProgram
{
 static void Main(string[] args)
 {
  for(int i = 0; i < 10; i++)
  Console.WriteLine("-> {0}", Teenager.Complain());
 }
}

Statické třídy

Zde program v metodě Main vypíše na konzoli aktuální čas a datum. V komentáři je uvedená instance třídy, při které by nám překladač hodil chybu.

using System;

static class UtilityClass
{

 public static void vytiskniCas()
 {
  Console.WriteLine(DateTime.Now.ToShortTimeString());
 }

 public static void vytiskniDatum()
 {
   Console.WriteLine(DateTime.Today.ToShortDateString());
 }
}

class hlavni
{
    static void Main(string[] args)
    {
    UtilityClass.vytiskniCas();
    // UtilityClass u = new UtilityClass();
    UtilityClass.vytiskniDatum();

    }
}

Statické konstruktory

Rozdíl oproti předchozímu příkladu je ten, že jsme změnili třídu SavingsAccount. CurrInterestRate se obnoví na původní hodnotu pokažde, když se vytvoří nový objekt SavingsAccount. Jako v následujícím příkladě. Avšak mohou pomocí statický dat změnit hodnoutu, mrkněte na poslední výstup. Autor knihy se však zmiňuje o tom, že to nepůjde, když budu chtít načíst data z databáze nebo z externího souboru. Proto se musí použít statický konstruktor.

using System;                                                         

class SavingsAccount
{
    public double currBalance;
    public static double currInterestRate = 0.05;

    public SavingsAccount(double balance)
    { currBalance = balance;
    currInterestRate = 0.123;
    }

    public static void SetInterestRate(double newRate) //S.T.A.T.I.C.K.A
    { currInterestRate = newRate; }

    public static double GetInterestRate()  //S.T.A.T.I.C.K.A
    { return currInterestRate;  }

    public void SetInterestRateObj(double newRate)
    { currInterestRate = newRate; }

    public double GetInterestRateObj()
    { return currInterestRate; }
}


class hlavniProgram
{

static void Main(string[] args)
  {
    SavingsAccount s1 = new SavingsAccount(9);
    SavingsAccount s2 = new SavingsAccount(109);

    Console.WriteLine("Urokova mira je : {0}", s1.GetInterestRateObj());
    Console.WriteLine("Urokova mira je : {0}", s2.GetInterestRateObj());   
    Console.WriteLine("Urokova mira je : {0}", SavingsAccount.GetInterestRate());

    s2.SetInterestRateObj(0.08);

    SavingsAccount s3 = new SavingsAccount(10000.75);
    
    Console.WriteLine("Urokova mira je : {0}", SavingsAccount.GetInterestRate());
    
    SavingsAccount.SetInterestRate(0.934);
    Console.WriteLine("Urokova mira je : {0}", s3.GetInterestRateObj());
  }
}



Statické členské proměnné určené pouze ke čtení

using System;

class Tire
{
    public static readonly Tire GoodStone = new Tire(90);
    public static readonly Tire FireYear = new Tire(100);

    public int manufactureID;
    public Tire() { }
    public Tire(int ID)
    { manufactureID = ID; }
}

class hlavniProgram
{
    static void Main()
    {
        Tire myTire = Tire.FireYear;
        Console.WriteLine("ID mych pneumatik je: {0}", myTire.manufactureID);
        Tire myTires = Tire.GoodStone;
        Console.WriteLine("ID mych pneumatik je: {0}", myTires.manufactureID);
    }
}