Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2_OOP_2_sem.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
238 Кб
Скачать
☆

Класи і структури

Структура – це окремий випадок класу. Історично структури використовуються в мовах програмування раніше класів. У мовах PL/1, C, Pascal вони були тільки сукупністю даних (полів класу), але не включали ні методів, ні подій. У мові С++ можливості структур були істотно розширені, і вони стали справжніми класами, хоча і з деякими обмеженнями. У мові C# збережений саме такий підхід до структур.

Чим слід керуватися, роблячи вибір між структурою і класом? Можна скористатися наступними правилами:

  • якщо необхідно віднести клас до розгорненого типу, робіть його структурою;

  • якщо в класі число полів відносно невелике, а число можливих об'єктів відносно велике, робіть його структурою. В цьому випадку пам'ять об'єктам відводитиметься в стеку, не створюватимуться зайві посилання, що дозволить підвищити ефективність використання пам'яті;

  • у решті випадків проектуйте справжні класи.

Оскільки на структури накладаються додаткові обмеження, може виникнути необхідність в компромісі – погодитися з обмеженнями і використовувати структуру або пожертвувати разгорнутістью і ефективністю і працювати із справжнім класом. Варто відзначити: коли мова йде, що вбудовані типи – int, а інші – є класами, то, насправді, мова йде про класи, реалізованих у вигляді структур.

Структури

Розглянемо тепер детальніше питання опису структур, їх синтаксису, семантики і тих особливостей, що відрізняють їх від класів.

Синтаксис структур

Синтаксис оголошення структури аналогічний синтаксису оголошення класу:

[атрибути][модифікатори]struct ім’я_структури [:список_інтерфейсів]

{тіло_структури}

Які зміни відбулися в синтаксисі заголовка структури порівняно з синтаксисом класу? Їх небагато:

  • ключове слово class змінене на слово struct ;

  • список батьків, який міг включати ім'я батьківського класу, замінений списком, що допускає тільки імена інтерфейсів. Для структур не може бути заданий батько (клас або структура). Відмітьте, структура може успадковувати інтерфейси;

  • для структур не застосовні модифікатори abstract і sealed. Причиною є відсутність механізму спадкоємства.

Все, що може бути вкладене в тіло класу, може бути вкладено і в тіло структури: поля, методи, конструктори та інше, включаючи класи і інтерфейси.

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

Розглянемо обмеження, що накладаються на структури.

Структури і спадкоємство

Найсерйозніше обмеження — пов'язане з обмеженням спадкоємства. Для структури не може бути заданий батьківський клас або батьківська структура. У структури не може бути спадкоємців. Звичайно, всяка структура, як і будь-який клас в C#, є спадкоємцем класу object, успадковувавши всі властивості і методи цього класу. Структура може успадковувати один або декілька інтерфейсів, реалізовуючи методи цих інтерфейсів.

З чим пов'язано таке серйозне обмеження. Одне з пояснень полягає в наступному. Розглянемо привласнення

у = x;

При привласненні допустимо, щоб у належав батьківському класу, а x – його нащадкові. При посилальному привласненні жодних проблем не виникає. В результаті привласнення посилання у указуватиме на об'єкт нащадка, який крім полів батька може мати додаткові поля. Головне, що всі поля батька будуть визначені. Після такого привласнення можливо і зворотне привласнення з приведенням типу

x = (T)y;

Для структур, що належать до значущого типу, подібне привласнення між батьком і нащадком було б неможливим. Батьку не можна привласнити об'єкт нащадка, оскільки у батька менше полів, чим у нащадка, тому можна було б привласнити лише частину полів. А вже у зворотний бік операція привласнення була б принципово неможлива. І це одна з причин, по якій зважилися відмовитися від спадкоємства для значущих типів в мові C#.