Статичні класи, методи, змінні. Статичні конструктори. Ключове слово static

Статичні класи, методи, змінні. Статичні конструктори. Ключове слово static


Зміст


1. Які елементи мови програмування C# можна оголошувати статичними?

У мові програмування C# статичними можуть бути:

  • класи;
  • методи;
  • змінні.

Щоб клас (метод, змінна) був статичним, перед його оголошенням ставиться ключове слово static.

 

2. Поняття статичного класу. Які особливості використання статичних класів у програмах на C#? Ключове слово static

З точки зору синтаксису C# статичний клас – це клас, який оголошується з ключовим словом static.

Загальна форма оголошення статичного класу:

static class ClassName
{
  // поля та методи класу
  // ...
}

де ClassName – ім’я статичного класу.

 

3. Властивості статичного класу

Реалізація програмного коду статичного класу нічим не відрізняється від програмного коду звичайного класу за винятком двох основних властивостей. У порівнянні з нестатичним класом, статичний клас має наступні властивості (відмінності):

  • неможна створювати об’єкти статичного класу;
  • статичний клас повинен містити тільки статичні члени.

 

4. Приклади, що демонструють властивості статичного класу

Приклад 1. Нехай задано статичний клас MyStaticClass. У цьому класі оголошується один статичний член з іменем d.

// статичний клас
static class MyStaticClass
{
  public static int d = 0;
}

Якщо спробувати створити об’єкт статичного класу

// спроба створити об'єкт статичного класу
MyStaticClass ms; // помилка - неможна створювати об'єкт статичного класу

то виникне помилка компіляції з повідомленням:

Cannot declare a variable of static type

що означає:

Неможливо оголосити змінну статичного типу

Приклад 2. Даний приклад демонструє правило, що статичний клас повинен містити тільки статичні члени. Нехай задано статичний клас MyStaticClass. Якщо у статичному класі MyStaticClass спробувати оголосити нестатичний член d цілого типу

// статичний клас
static class MyStaticClass
{
  // нестатичний член, без ключового слова static
  public int d = 0; // помилка - неможна оголошувати нестатичнй екземпляр в статичному класі
}

то під час компіляції компілятор видасть наступну помилку:

Cannot declare instance members in a static class

що означає

Неможна оголошувати члени екземпляри в статичному класі

 

5. Приклади статичних класів

Приклад 1. У даному прикладі демонструється використання статичної змінної у статичному класі. Оголошується статичний клас з іменем Count, в якому міститься одна статична змінна count. Ця статична змінна є лічильником, яка спільно використовується у нестатичних методах Add1(), Add2() іншого класу Methods.
Програмний код класів Count та Methods наступний:

// статичний клас Count
static class Count
{
  // статична змінна count у класі Count - спільний ресурс
  public static int count;
}

// нестатичний клас
class Methods
{
  // методи нестатичного класу мають доступ
  // до статичної змінної count статичного класу Count
  public void Add1() // нестатичний метод
  {
    // зміна значення статичної змінної
    Count.count++;
  }

  public static void Add2() // статичний метод
  {
    Count.count = Count.count + 2;
  }
}

У нижченаведеному коді продемонстровано звертання до змінної count класу Count та зміна значення цієї змінної з методів Add1(), Add2().

Methods M = new Methods(); // створити об'єкт класу Methods

// перевірити значення статичного члена
int n = Count.count; // n = 0

// викликати нестатичний метод Add1() класу Methods
M.Add1(); // збільшення Count.count на 1
n = Count.count; // n = 1

Як видно з прикладу, статичний член даних Count.count є спільним для методів Add1(), Add2() класу Methods. Якби у програмі були реалізовані інші класи з деякими методами, то до цього члена даних можна було б звертатись з цих методів.

Якщо у даному прикладі клас Count оголосити як нестатичний (без ключового слова static)

// клас Count - нестатичний
class Count
{
  // статична змінна count у класі Count - спільний ресурс
  public static int count;
}

...

то результат роботи програми не зміниться. Статичну змінну Count.count можна використовувати так само як спільний ресурс.

Приклад 2. Приклад демонструє використання статичного методу у нестатичному класі. Статичний метод виступає спільним ресурсом, який виконує деяку спільну роботу.

У прикладі оголошується статичний метод AbsComplex(), який знаходить модуль комплексного числа. Метод оголошується у класі ComplexLibrary. Також оголошуються 2 класи, які містять методи, що використовують метод AbsComplex() у своїх обчисленнях.

// нестатичний клас що містить статичний метод
class ComplexLibrary
{
  // статичний метод, обчислює модуль комплексного числа
  // отримує значення дійсної (а) та уявної (b) частини комплексного числа
  public static double AbsComplex(double a, double b)
  {
    return Math.Sqrt(a * a + b * b);
  }
}

// клас, що містить нестатичний метод, який використовує статичний метод AbsComplex
class CalcComplex1
{
  // нестатичний метод
  // визначає, чи 2 комплексні числа рівні між собою
  // даний метод використовує статичний метод ComplexLibrary.AbsComplex() для обчислень
  public bool EqualComplex(double a1, double b1, double a2, double b2)
  {
    double value1, value2;

    // використання статичного методу AbsComplex()
    value1 = ComplexLibrary.AbsComplex(a1, b1);
    value2 = ComplexLibrary.AbsComplex(a2, b2);

    return value1 == value2;
  }
}

// ще один клас, який використовує метод AbsComplex() з класу ComplexLibrary
class CalcComplex2
{
  // метод, що визначає чи довжина комплексного числа рівна 0
  public bool ZeroComplex(double a, double b)
  {
    double value = ComplexLibrary.AbsComplex(a, b);
    return value == 0.0;
  }
}

Використання методів класів CalcComplex1, CalcComplex2 може бути таким:

CalcComplex1 c1 = new CalcComplex1(); // створити екземпляр (об'єкт) класу
CalcComplex2 c2 = new CalcComplex2();

bool f;

f = c1.EqualComplex(3, 4, 2, 5); // f = False
f = c1.EqualComplex(1, 2, 2, 1); // f = True
f = c1.EqualComplex(-1, 2, -2, 1); // f = True
f = c2.ZeroComplex(0, 0); // f = True
f = c2.ZeroComplex(1, -5); // f = False

 

6. Які переваги застосування статичних класів, методів та змінних у програмах на C#?

Статичні класи, методи та змінні ефективні у наступних випадках:

  • коли потрібно створити так звані методи розширення. Методи розширення використовуються для розширення функцій класу. Ці методи є статичними;
  • коли у програмі є деякий спільний ресурс, до якого можуть мати звертання методи різних класів які обробляють даний ресурс (читають або змінюють його значення). Цей спільний ресурс оголошується як статична змінна. Наприклад, таким ресурсом може бути деякий лічильник викликів, метод що реалізує унікальну обробку, унікальна файлова змінна (ресурс) тощо;
  • коли потрібно об’єднати між собою групи статичних методів;
  • коли потрібно використовувати спільні приховані (private) дані класу та організовувати доступ до цих даних зі статичних та нестатичних методів.


 

7. Чим відрізняється виклик статичного методу від нестатичного?

У будь-якому нестатичному класі може бути оголошено як статичні методи, так і нестатичні. Відмінність між викликом статичного та нестатичного методу класу полягає в наступному:

  • щоб викликати нестатичний метод класу, потрібно створити екземпляр (об’єкт) цього класу. Статичний метод викликається без створення об’єкту класу – перед іменем методу вказується ім’я класу, в якому цей статичний метод оголошений.

Наприклад. Задано нестатичний клас Sqr, що містить наступні два методи, які повертають квадрат цілочисельного значення:

  • GetSqr() – нестатичний метод;
  • GetSqrStatic() – статичний метод.
// нестатичний клас, що містить нестатичний та статичний методи
class Sqr
{
  // нестатичний метод
  public int GetSqr(int x)
  {
    return x * x;
  }

  // статичний метод
  public static int GetSqrStatic(int x)
  {
    return x * x;
  }
}

Нижче продемонстровано виклик та використання цих методів:

// Демонстрація виклику статичного та нестатичного методів класу
int t;

// 1. Виклик нестатичного методу класу Sqr
// Потрібно створити об'єкт класу
Sqr sc = new Sqr();
t = sc.GetSqr(7); // t = 49

// 2. Виклик статичного методу класу Sqr
t = Sqr.GetSqrStatic(7); // t = 49

Як видно з вищенаведеного коду, щоб викликати статичний метод деякого класу, перед його іменем потрібно вказати ім’я цього класу.

 

8. Чи можна оголошувати приватний (private) статичний член у деякому класі?

Так можна. У цьому випадку, цей статичний член класу буде доступний тільки в межах цього класу, тобто з методів цього класу. Доступ з методів інших класів буде неможливий.

 

9. Чи можна оголошувати статичний член класу з модифікатором доступу protected?

Так можна. У цьому випадку, доступ до статичного члену класу будуть мати методи класу, який є успадкованим від даного.

Наприклад. Задано клас A, що містить один статичний член a, який оголошено як protected. Також задано клас B, який успадковує (розширює) клас A. З методу SomeMethod() класу B здійснюється доступ до protected-змінної класу A.

// нестатичний клас, що містить нестатичний та статичний методи
class A
{
  protected static int a;
}

// клас B успадковує (розширює) клас A
class B : A
{
  void SomeMethod()
  {
    a = 10; // доступ до protected-змінної класу A
  }
}

 

10. Чи може нестатичний клас містити статичні змінні та статичні методи?

Так може. Приклади використання статичних методів у нестатичному класі наведено у пунктах 5 та 7.

 

11. Чи можна поєднувати статичні та нестатичні методи в одному класі?

Так, можна. Але тільки у нестатичному класі. Якщо клас оголошено як статичний, то усі методи та змінні класу мають бути також статичні (див. п. 4 – Приклад 2).

Наприклад. Приклад демонструє поєднання статичного та нестатичного методів класу для доступу до прихованої статичної змінної t у класі Оголошується нестатичний клас CMyClass, що містить статичну змінну, статичний та нестатичний методи доступу до неї.

// нестатичний клас, що поєднує статичні та нестатичні елементи
class CMyClass
{
  // статична змінна, оголошена як private
  private static int t;

  // статичний метод, що змінює значення статичної змінної t
  public static void Set(int _t)
  {
    t = _t;
  }

  // нестатичний метод, що читає значення статичної змінної t
  public int Get() { return t; }
}

У нижченаведеному коді продемонстровано доступ до прихованої статичної змінної t класу CMyClass

// демонстрація поєднання статичних та нестатичних членів класу
int x;

// 1. Доступ до прихованої (private) статичної змінної через статичний метод Set
CMyClass.Set(777); // статична змінна t = 777

// 2. Прочитати значення прихованої (private) статичної змінної t
// 2.1. Створити об'єкт класу
CMyClass mc = new CMyClass();

// 2.2. Викликати нестатичний метод Get() через екземпляр класу
x = mc.Get(); // x = 777 - поточне значення статичної змінної

Даний приклад добре демонструє, як можна організувати роботу зі спільними, прихованими даними класу.

 

12. Чи можна у статичному методі статичного класу створити об’єкт нестатичного класу?

Так, можна. Класичний приклад цьому, функція Main() для консольних додатків. Ця функція оголошена як static. Однак, створювати екземпляри будь-яких нестатичних класів у цій функції можна.

 

13. Що таке статичні конструктори? Приклад

Статичні конструктори дозволяють ініціалізувати статичні змінні класу.

Приклад. Демонструється оголошення статичного конструктора у класі.

// клас, що містить статичний конструктор
class CCount
{
  private static int count;

  static CCount()
  {
    count = 7; // ініціалізація статичної змінної count
  }

  // доступ до внутрішньої статичної змінної count
  public static int Get()
  {
    return count;
  }
}

Демонстрація роботи класу CCount у деякому методі

int x;
x = CCount.Get(); // x = 7

 

14. Які правила (особливості) використання статичних конструкторів?

При використанні статичних конструкторів потрібно звернути увагу на такі правила:

  • перед статичним конструктором має вказуватись ключове слово static;
  • статичні конструктори викликаються автоматично, коли клас завантажується перший раз;
  • у статичних конструкторів не має бути модифікаторів доступу (public, private). Тобто, статичні конструктори користуються доступом за замовчуванням. Це зв’язано з тим, що статичні конструктори викликаються у класі першими, перед створенням першого екземпляру класу в програмі;
  • статичний конструктор не може мати параметрів. Якщо спробувати створити параметризований статичний конструктор у класі, то виникне помилка компіляції.

 

15. Чи можна зі статичних конструкторів ініціалізувати нестатичні змінні класу?

Ні, не можна. Зі статичних конструкторів можна ініціалізовувати тільки статичні змінні цього ж класу. Якщо у цьому класі також оголошуються нестатичні змінні, то доступу до них зі статичних конструкторів немає.

Наприклад.

class CFileName
{
  private static string fname; // прихована статична змінна
  private string folder; // прихована нестатична змінна

  // статичний конструктор
  static CFileName(string _fname)
  {
    fname = _fname; // доступ тільки до статичних змінних класу
    // folder = ""; // помилка, folder - нестатична змінна
  }
}

 


Зв’язані теми