MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Membri statici și modificatorul static

În afară de câmpurile, metodele și proprietățile obișnuite, clasele și structurile pot avea câmpuri, metode și proprietăți statice. Câmpurile, metodele și proprietățile statice se referă la întreaga clasă/structură și pentru a accesa astfel de membri nu este necesar să se creeze o instanță a clasei/structurii.

Câmpuri statice

Câmpurile statice stochează starea întregii clase/structuri. Un câmp static este definit la fel ca unul obișnuit, doar că înainte de tipul câmpului se adaugă cuvântul cheie static. De exemplu, să considerăm clasa Person, care reprezintă o persoană:

Person bob = new(68);
bob.СheckAge();     // Deja la pensie

Person tom = new(37);
tom.СheckAge();     // Câți ani mai sunt până la pensie: 28

// obținerea câmpului static
Console.WriteLine(Person.retirementAge); // 65
// modificarea câmpului static
Person.retirementAge = 67;

class Person
{
   int age;
   public static int retirementAge = 65;
   public Person(int age)
   {
       this.age = age;
   }
   public void СheckAge()
   {
       if (age >= retirementAge)
           Console.WriteLine("Deja la pensie");
       else
           Console.WriteLine($"Câți ani mai sunt până la pensie: {retirementAge - age}");
   }
}

În acest caz, clasa Person are două câmpuri: age (stochează vârsta persoanei) și retirementAge (stochează vârsta de pensionare). Însă câmpul retirementAge este static. El nu se referă la o persoană concretă, ci la toate persoanele. (În acest caz, pentru simplificare, ignorăm faptul că vârsta de pensionare poate varia în funcție de sex și profesie.)

Astfel, câmpul retirementAge nu se referă la un obiect separat și nu stochează valoarea unui obiect separat al clasei Person, ci se referă la întreaga clasă Person și stochează o valoare comună pentru întreaga clasă.

În clasă putem folosi acest câmp ca orice alt câmp. De exemplu, în metoda СheckAge(), care verifică statutul de pensionare al persoanei, pentru verificare folosim acest câmp:

if (age >= retirementAge)

Dar dacă dorim să accesăm acest câmp în afara clasei, putem face acest lucru folosind numele clasei:

Console.WriteLine(Person.retirementAge);
Person.retirementAge = 67;

La nivelul memoriei, pentru câmpurile statice se va crea o zonă în memorie care va fi comună pentru toate obiectele clasei.

Memoria pentru variabilele statice este alocată chiar și în cazul în care nu a fost creat niciun obiect al acestei clase.

Proprietăți statice

În mod similar, putem crea și folosi proprietăți statice:

Person bob = new(68);
bob.СheckAge();

Console.WriteLine(Person.RetirementAge); // 65

class Person
{
   int age;
   static int retirementAge = 65;
   public static int RetirementAge
   {
       get { return retirementAge; }
       set { if (value > 1 și value < 100) retirementAge = value; }
   }
   public Person(int age)
   {
       this.age = age;
   }
   public void СheckAge()
   {
       if (age >= retirementAge)
           Console.WriteLine("Deja la pensie");
       else
           Console.WriteLine($"Câți ani mai sunt până la pensie: {retirementAge - age}") ;
   }
}

În acest caz, accesul la variabila statică retirementAge este intermediat prin proprietatea statică RetirementAge.

Astfel, variabilele și proprietățile care stochează starea comună pentru toate obiectele clasei/structurii trebuie definite ca statice.

Adesea, câmpurile și proprietățile statice sunt folosite pentru stocarea contoarelor. De exemplu, dorim să avem un contor care să ne permită să aflăm câte obiecte Person au fost create:

var tom = new Person();
var bob = new Person();
var sam = new Person();
Console.WriteLine(Person.Counter);  // 3

class Person
{
   static int counter = 0;
   public static int Counter => counter;
   public Person()
   {
       counter++;
   }
}

În acest caz, în clasa Person, contorul este stocat într-o variabilă privată counter, a cărei valoare crește cu unu la crearea unui obiect în constructor. Iar cu ajutorul proprietății statice Counter, care este disponibilă doar pentru citire, putem obține valoarea contorului.

Metode statice

Metodele statice definesc un comportament comun pentru toate obiectele, care nu depinde de un obiect specific. Pentru a accesa metodele statice se folosește de asemenea numele clasei/structurii:

Person bob = new(68);
Person.CheckRetirementStatus(bob);

class Person
{
   public int Age { get; set; }
   static int retirementAge = 65;
   public Person(int age) => Age = age;
   public static void CheckRetirementStatus(Person person)
   {
       if (person.Age >= retirementAge)
           Console.WriteLine("Deja la pensie");
       else
           Console.WriteLine($"Câți ani mai sunt până la pensie: {retirementAge - person.Age}") ;
   }
}

În acest caz, în clasa Person este definită metoda statică CheckRetirementStatus(), care primește ca parametru un obiect Person și îi verifică statutul de pensionare.

Trebuie să ținem cont că metodele statice pot accesa doar membrii statici ai clasei. Nu putem accesa metode, câmpuri sau proprietăți nestatice în cadrul unei metode statice.

Constructor static

În afară de constructorii obișnuiți, clasa poate avea și constructori statici. Constructorii statici au următoarele caracteristici distinctive:

  • Constructorii statici nu trebuie să aibă modificator de acces și nu acceptă parametri
  • Ca și în metodele statice, în constructorii statici nu se poate folosi cuvântul cheie this pentru referință la obiectul curent al clasei și se pot accesa doar membrii statici ai clasei
  • Constructorii statici nu pot fi apelați manual în program. Ei sunt executați automat la prima creare a unui obiect al acestei clase sau la primul acces la membrii săi statici (dacă există)
  • Constructorii statici sunt de obicei folosiți pentru inițializarea datelor statice sau pentru a efectua acțiuni care trebuie realizate doar o dată

Să definim un constructor static:

Console.WriteLine(Person.RetirementAge);

class Person
{
   static int retirementAge;
   public static int RetirementAge => retirementAge;
   static Person()
   {
       if (DateTime.Now.Year == 2022)
           retirementAge = 65;
       else
           retirementAge = 67;
   }
}

În acest caz, folosim structura integrată DateTime pentru a obține anul curent. Pentru aceasta se folosește proprietatea DateTime.Now.Year. dacă este egal cu 2022, setăm o anumită vârstă de pensionare. În caz contrar, setăm o altă valoare pentru vârsta de pensionare.

Clase statice

Clasele statice sunt declarate cu modificatorul static și pot conține doar câmpuri, proprietăți și metode statice. De exemplu, să definim o clasă care efectuează o serie de operații aritmetice:

Console.WriteLine(Operations.Add(5, 4));         // 9
Console.WriteLine(Operations.Subtract(5, 4));    // 1
Console.WriteLine(Operations.Multiply(5, 4));    // 20

static class Operations
{
   public static int Add(int x, int y) => x + y;
   public static int Subtract(int x, int y) => x - y;
   public static int Multiply(int x, int y) => x * y;
}
← Lecția anterioară Lecția următoare →