Скачиваний:
30
Добавлен:
26.03.2016
Размер:
429.43 Кб
Скачать

Статичний конструктор

При створенні класу створюються статичні поля, які прямо при створенні отримують конкретні (статичні) значень. Наприклад static Rate=0.12;. А як бути у випадках, коли значення статичного поля визначається не у момент створення класу, а у момент роботи застосування, коли із застосування треба звернутися до бази даних, щоб взяти звідти, наприклад, значення процентної ставки? І це все треба зробити до створення об'єкту. І поле процентної ставки має атрибут static. Такі проблеми вирішує так званий статичний конструктор, який виконується всього один раз перед конструктором, який створює об'єкти. Статичний конструктор використовується для ініціалізації будь-яких статичних даних або для певної дії, яку потрібно виконати тільки один раз. Він викликається автоматично перед створенням першого екземпляра або коли йде перше звернення до статичного члена. Ось приклад:

class SimpleClass

{

// Статична змінна, яка повинна бути

// ініціалізована під час виконання програми:

static long dt;

// Статичний конструктор, який викликається тільки

// один раз перед будь-яким конструктором, який створює

// екземпляр класу, або при першій зустрічі змінної dt:

static Simpleclass()

{

dt = DateTime.Now.Ticks;

}

}

Виконавче середовище викличе цей конструктор перед створенням екземпляра класу SimpleClass і перед першим зверненням до змінної dt.

Статичні класи

Якщо всі члени класу - статичні, то має сенс винести слово static "за дужки" і оголосити весь клас статичним. Наприклад запис static class Myclass {} буде правильним.

Принципи об'єктно-орієнтованого програмування

Таких принципів - три: інкапсуляція, спадкоємство і поліморфізм. У попередньому матеріалі ми частково торкалися цих понять, але не загострювали на них увагу. Тепер настав час розглянути сутність цих принципів докладніше.

Інкапсуляція

Капсула латинською мовою означає "коробочка", ін - прийменник "В". Тому дослівний переклад першого принципу ООП - "в коробочці". У нашому випадку це умовна коробочка, чорний ящик, в якій ховаються всі деталі реалізації проблеми, але за допомогою цього ящика програміст може вирішити саму проблему, не відволікаючись на деталі її реалізації. Крім того, "коробочка" містить (зберігає) дані, причому таким чином, що до них немає прямого доступу ззовні. Є доступ тільки з допомогою методів, які зберігаються теж в коробочці. У такий спосіб забезпечується захист даних від зовнішнього втручання. Той, хто в старі часи програмував введення-виведення, знає, яка це була морока. Сьогодні є такий клас, як, наприклад, Console, в якому містяться (заховані в деталях) методи Read(), ReadLines(), які забезпечують введення даних з клавіатури, і ні у одного програміста не болить голова, що буде робити в програмі блок введення-вивення. Все заховано в класі Console. Пиши собі рядок string s = ReadLines();, і твоя проблема введення з клавіатури вирішена.

Інша сторона - в коробочці заховані дані про стан об'єкта, який описаний в ній. До цих даних просто так не дістатися, якщо їм присвоїти атрибут private. Тільки через спеціальні методи, які знаходяться там же, в коробочці (як ми побачимо - це методи з іменами get (отримати дані) і set (встановити дані в певне значення)). Тобто просто так змінити безпосередньо стан об'єкта і тим самим, можливо, зруйнувати його не вийде. Це все ми спостерігали, коли створювали простий клас, правила побудови якого включають у себе дотримання принципу інкапсуляції.

Чим же, якими синтаксичними засобами мови забезпечується дотримання принципу інкапсуляції при створенні класу? Це використання ключових слів public, private, protected (з ними ми вже зустрічались) та internal. Сенс останнього буде розглянутий пізніше. Раніше ми вже звертали увагу на той факт, що коли задаються поля класу (а саме вони визначають своїми значеннями стан в даний момент об'єкта класу), ці поля повинні задаватися з атрибутом private щоб до них ззовні не було доступу. У такому разі вони доступні тільки для методів, визначених в даному класі.

Що стосується загальнодоступних (з атрибутом public) даних, то такими даними можуть бути загальнодоступні константи, інші поля які визначені лише для читання. Останні мають спеціальний атрибут readonly. Але чим відрізняються константи від полів "тільки для читання"? Річ у тому, що константи не завжди відповідають всім вимогам ситуації з реалізацією алгоритму. Часто трапляється так, що змінну потрібно отримати в результаті розрахунків, а потім зробити її "тільки для читання". У C# саме для таких випадків передбачений тип змінних readonly. Змінні поля readonly мають більшу гнучкість, ніж const (атрибут, з яким оголошується константа), тому що дозволяють перед присвоєнням здійснювати різні обчислення значення, яке повинне бути "тільки для читання". Правило використання таких полів говорить, що ви можете присвоювати їм значення тільки в конструкторі і ніде більше (лише конструктор ініціалізує поля, це його функція). Однією з основних особливостей таких полів є те, що вони можуть належати й екземплярам класу, а не бути статичними, як константи (при оголошенні константи атрибут static заборонений, бо за своєю суттю константа - вже сама по собі статичний елемент). Це дозволяє отримувати різні значення полів "тільки для читання" в різних екземплярах класів. Але якщо ви хочете зробити поле readonly статичним, то повинні явно оголосити його таким, на відміну від полів const.

Розглянемо приклад. Нехай в деякому класі А є метод обчислення числа постачальників supp(). Об'єкти, які отримуються з класу А, повинні працювати якийсь час з одним числом постачальників, а через деякий проміжок - з іншим числом. Тобто на певному відрізку часу поле "Число постачальників", назвемо його NumSupp, повинно бути як би константою.

В описаному прикладі код може виглядати так:

public class A

{

public static readonly uint NumSupp;

static A() // статичний конструктор

{

NumSupp = supp(Data);

}

}

У цьому конкретному прикладі ми оголошуємо нашу змінну як статичну і використовуємо її в екземплярі класу при кожному запуску програми. Функція supp(Data) обчислить число постачальників на дану дату, і за допомогою конструктора поле NumSupp отримає задане значення, з яким почнуть працювати всі екземпляри класу.

Ми говорили раніше, що управління приватними даними класу здійснюється двома методами з іменами get і set. Проте є ще один спосіб управління цими даними: визначення властивості. Розглянемо інкапсуляцію з використанням методів get і set.