Назад
Вперед
Зміст
Статичні елементи
Об'єктно-орієнтований стиль програмування можна коротко описати таким чином:
- Спочатку створіть класи – корисні правила для створення об'єктів.
- Далі створюйте об'єкти – екземпляри цих класів та змушуйте їх виконувати потрібну Вам роботу.
Отже, у процесі виконання програми безпосередньо діють об'єкти. Однак у деяких випадках краще вважати, що дії виконуються самим класом. Хорошим прикладом є клас Math - всі його методи викликаються від імені класу:
Console.WriteLine(Math.Sin(0.5)+Math.Cos(0.5));
|
|---|
Було б досить дивно для обчислювання математичних функцій спочатку створювати об'єкт-«математику»:
Math m1=new Math(); Math m2=new Math();
Console.WriteLine(m1.Sin(0.5)+m2.Cos(0.5))
|
|---|
Це означало б, що можна створювати кілька математик. Але вони всі повинні діяти абсолютно однаково.
Аналогічно справа і зі змінними - бувають випадки, коли деякі дані краще представляти не як порцію інформації, що належить об'єкту, а класу в цілому.
У класі Math ця ситуація зустрічається при доступі до тригонометричної константи - Math.PI.
Елементи класу (змінні та методи), які співвідносяться не з об'єктами, а з класом, називаються статичними. В описі статичних елементів використовують ключове слово static.
Статичні змінні описуються і зберігаються в класі в одному екземплярі.
На відміну від статичних членів звичайні елементи класу називаються елементами екземплярів класу – методи екземплярів та змінні екземплярів. Змінні екземпляри описуються у класі та зберігаються в об'єктах класу.
Приклад 1
Наведемо приклад класу зі статичним полем та статичним методом
Визначимо клас Tiger. Нехай він містить:
- Поле count, у якому зберігатимемо інформацію про кількість створених тигрів. Це поле не може належати до кожного конкретного тигру, воно має бути спільним для всіх тигрів. Таке поле слід описувати зі специфікатором static;
- Створимо конструктор, в якому будемо збільшувати лічильник count при створенні кожного нового об'єкта.
- Напишемо також статичний метод Number, який виводить на екран кількість створених об'єктів.
public class Tiger
{
public static int count;
public Tiger()
{
count++;
}
public static void Number()
{
Console.WriteLine("Тигрів = {0}", count);
}
}
|
У класі Program:
- Створити кілька тигрів;
- За допомогою методу Number визначити, скільки тигрів було створено?
static void Main(string[] args)
{
// Чому дорівнює число тигрів без створення об'єктів?
Tiger.Number(); // виведе 0, т.к. ми поки не створили об'єкти
// 0, т.к. ми поки не створили об'єкти
// Створимо 3 тигра
Tiger t1 = new Tiger();
Tiger t2 = new Tiger();
Tiger t3 = new Tiger();
Tiger.Number(); // виведе 3 тигра
Console.ReadLine();
}
|
Результат:
Чому спочатку виходить 0, адже змінна count на початку програми не набула жодного значення?
Статичні поля не можуть розглядатися як неініціалізовані значення.
Тому, якщо вони доступні, перш ніж їм було надано значення, то їм надається значення, яке використовується за умовчанням для цього типу даних.
Для цілого значення це нуль.
Приклад 2
Наведемо приклад класу зі статичними та нестатичними полями та статичними та нестатичними методами
Визначимо клас Person, який моделює ситуацію, коли декілька людей мають деякий загальний запас їжі і ділять його порівну.
Клас містить:
- Поле кількість їжі FoodQuantity. Це поле не може відноситися до кожної конкретної людини, воно має бути спільним для всіх людей. Тому опишемо його зі специфікатором static;
- Поле кількість людей PeopleCount. Аналогічно теж опишемо його зі специфікатором static;
- Поле вага людини weight. Це характеристика конкретної людини, тому це поле не статичне;
- Властивість Weight для читання значень поля weight;
- Конструктор, в якому будемо збільшувати лічильник PeopleCount при створенні кожного нового об'єкта. Тут ми задаємо вагу людини. Усі люди будуть у нас мати вагу 10;
- Не статичний метод ToEat, який показує, що людина поїла. Людина з'їдає кількість їжі t = FoodQuantity /2.0/PeopleCount. Після цього вага людини збільшується на t, а кількість їжі зменшується на t.
- Статичний метод Description, який показує, скільки всього є людей і скільки їжі залишилося.
class Person
{
// всього їжі
public static double FoodQuantity = 100.0;
//кількість людей
public static int PeopleCount = 0;
//вага вес людини
double weight;
//конструктор об'єкта
public Person()
{ weight = 10.0; PeopleCount++; }
//властивість вес людини
public double Weight
{ get { return weight; } }
//метод кушати
public void ToEat()
{
//з'їдає 1 людина
double t = FoodQuantity / 2.0 / PeopleCount;
//вес чел збільшується
weight += t;
//кількість їжі зменшується
FoodQuantity -= t;
}
public static string Description()
{
return String.Format("Людей - {0} Їжі - {1}",PeopleCount, FoodQuantity);
}
}
|
У класі Program:
- Створити людину;
- Вивести його вагу та вагу їжі до того, як людина поїсть
- За допомогою методу ToEat нехай людина поїсть.
- Вивести нову вагу людини та вагу їжі після того, як вона поїсть
Теж саме зробити ще для однієї людини.
static void Main(string[] args)
{
//створили об'єкт 1
Person p1 = new Person();
// вес людини
Console.WriteLine("Вес чел1 - {0}", p1.Weight);
//статичний метод
//скільки осталось їжі
Console.WriteLine(Person.Description());
//не статичний метод
//людина поїла
p1.ToEat();
// вес людини
Console.WriteLine("Вес чел1 - {0}", p1.Weight);
//статичний метод
//скільки осталось їжі
Console.WriteLine(Person.Description());
//створили об'єкт 2
Person p2 = new Person();
// вес людини
Console.WriteLine("Вес чел2 - {0}", p2.Weight);
p2.ToEat();
Console.WriteLine("Вес чел2 -{0}", p2.Weight);
Console.WriteLine(Person.Description());
Console.ReadKey();
}
|
Результат:
Вес чел1 - 10
Людей - 1 Їжі - 100
Вес чел1 - 60
Людей - 1 Їжі - 50
Вес чел2 - 10
Вес чел2 - 22,5
Людей - 2 Їжі - 37,5
|
|---|
Відмінності статичного методу від нестатичного
- Для виклику статичного методу не потрібний об'єкт.
- Всередині статичного методу недоступна змінна this, що вказує на об'єкт, відповідно недоступні всі нестатичні члени цього класу, т.к. як немає об'єкта.
- Всередині звичайного методу доступні як статичні, так і нестатичні поля.
- Можна і весь клас зробити статичним. По суті такі класи є контейнерами глобальних функцій, проте це відходить від концепції ООП. Також не можна буде створювати відповідно і екземпляри статичного класу.
Назад
Вперед
Зміст