Главная
Обратная связь
Дисциплины:
Архитектура (936) Биология (6393) География (744) История (25) Компьютеры (1497) Кулинария (2184) Культура (3938) Литература (5778) Математика (5918) Медицина (9278) Механика (2776) Образование (13883) Политика (26404) Правоведение (321) Психология (56518) Религия (1833) Социология (23400) Спорт (2350) Строительство (17942) Технология (5741) Транспорт (14634) Физика (1043) Философия (440) Финансы (17336) Химия (4931) Экология (6055) Экономика (9200) Электроника (7621)
|
Перевантаження методів. Рекурсивні методи
У C # допускається спільне використання одного і того ж імені двома або більше методами одного і того ж класу, за умови, що їх параметри оголошуються по-різному. У цьому випадку говорять, що методи перевантажуються, а сам процес називається перевантаженням методів. Перевантаження методів відноситься до одного із способів реалізації поліморфізму в C #. Загалом, для перевантаження методу досить оголосити різні його варіанти, а про решту подбає компілятор. Але при цьому необхідно дотримати наступне важлива умова: тип або число параметрів у кожного методу повинні бути різними. Абсолютно недостатньо, щоб два методи відрізнялися тільки типами повертаються значень. Вони повинні також відрізнятися типами або числом своїх параметрів. (Принаймні, типи повертаються значень дають недостатньо відомостей компілятору C #, щоб вирішити, який саме метод слід використовувати.) Зрозуміло, що перевантажуються методи можуть відрізнятися і типами повертаються значень. Коли викликається перевантажується метод, то виконується той його варіант, параметри якого відповідають (по типу і числу) переданим аргументам. Перевантаження методів підтримує властивість поліморфізму, оскільки саме таким способом в C # реалізується головний принцип поліморфізму: один інтерфейс - безліч методів. Для того щоб стало зрозуміліше, як це робиться, звернемося до конкретного прикладу. У мовах програмування, що не підтримують перевантаження методів, кожному методу повинно бути присвоєно унікальне ім'я. Але в програмуванні часто виникає потреба реалізувати по суті один і той же метод для обробки різних типів даних. Припустимо, що потрібно функція, що визначає абсолютне значення. У мовах, що не підтримують перевантаження методів, зазвичай доводиться створювати три або більше варіантів такої функції з дещо відмінними, але все ж різними іменами. Наприклад, в С функція abs () повертає абсолютне значення цілого числа, функція labs () - абсолютне значення довгого цілого числа, а функція fabs () - абсолютне значення числа з плаваючою точкою звичайної (одинарної) точності. В С перевантаження не підтримується, і тому у кожної функції має бути своє, особливе ім'я, незважаючи на те, що всі згадані вище функції, по суті, роблять одне й те саме - визначають абсолютне значення. Але це принципово ускладнює становище, оскільки доводиться пам'ятати імена всіх трьох функцій, хоча вони реалізовані по одному і тому ж основному принципу. Подібні труднощі в C # не виникають, оскільки кожному методу, який визначає абсолютне значення, може бути присвоєно одне і те ж ім'я. І дійсно, до складу бібліотеки класів для середовища .NET Framework входить метод Abs (), який перевантажується в класі System.Math для обробки даних різних числових типів. Компілятор C # сам визначає, який саме варіант методу Abs () слід викликати, виходячи з типу переданого аргументу. У C # визначено поняття сигнатури, що позначає ім'я методу і список його параметрів; Стосовно до перевантаження це поняття означає, що в одному класі не повинно існувати двох методів з однієї і тієї ж сигнатурою. Слід підкреслити, що в сигнатуру не входить тип значення, оскільки він не враховується, коли компілятор C # приймає рішення про перевантаження методу. У сигнатуру не входить також модифікатор params. У C # допускається, щоб метод викликався самого себе. Цей процес називається рекурсією, а метод, що викликає самого себе, - рекурсивним. Взагалі, рекурсія являє собою процес, в ході якого щось визначає само себе. У цьому відношенні вона чимось нагадує циклічне визначення. Рекурсивний метод відрізняється головним чином тим, що він містить оператор, в якому цей метод викликає самого себе. Рекурсія є ефективним механізмом управління програмою. Рекурсивні варіанти багатьох процедур можуть виконуватися трохи повільніше, ніж їх ітераційні еквіваленти через додаткових витрат системних ресурсів на неодноразові виклики методу. Якщо ж таких викликів виявиться занадто багато, то в кінцевому підсумку може бути переповнений системний стек. А оскільки параметри і локальні змінні рекурсивного методу зберігаються в системному стеку і при кожному новому виклику цього методу створюється їх нова копія, то в якийсь момент стек може виявитися вичерпаним. У цьому випадку виникає виняткова ситуація, і загальномовне виконуюча середовище (CLR) генерує відповідне виняток. Але турбуватися про це доведеться лише в тому випадку, якщо рекурсивна процедура виконується неправильно. Головна перевага рекурсії полягає в тому, що вона дозволяє реалізувати деякі алгоритми ясніше і простіше, ніж ітераційним способом. Наприклад, алгоритм швидкого сортування досить важко реалізувати ітераційним способом. А деякі завдання, наприклад штучного інтелекту, очевидно, вимагають саме рекурсивного рішення. При написанні рекурсивних методів слід неодмінно вказати у відповідному місці умовний оператор, наприклад if, щоб організувати повернення з методу без рекурсії. В іншому разі повернення з викликаного одного разу рекурсивного методу може взагалі не відбутися. Подібного роду помилка вельми характерна для реалізації рекурсії в практиці програмування. У цьому випадку рекомендується користуватися операторами, що містять виклики методу WriteLine (), щоб стежити за подіями в рекурсивному методі і перервати його виконання, якщо в ньому виявиться помилка.
|