перевантаження методів

перевантаження методів

Книга розрахована на широке коло читачів, які цікавляться програмуванням на C # .Введіте сюди коротку анотацію

Книга: C # 4.0: повне керівництво

перевантаження методів

У C # допускається спільне використання одного і того ж імені двома або більше методами одного і того ж класу, за умови, що їх параметри оголошуються по-різному. У цьому випадку говорять, що методи перевантажуються. а сам процес називається перевантаженням методів. Перевантаження методів відноситься до одного із способів реалізації поліморфізму в С #.

Загалом, для перевантаження методу досить оголосити різні його варіанти, а про решту подбає компілятор. Але при цьому необхідно дотримуватися наступного важлива умова: тип або число параметрів у кожного методу повинні бути різними. Абсолютно недостатньо, щоб два методи відрізнялися тільки типами значень, що повертаються. Вони повинні також відрізнятися типами або числом своїх параметрів. (У всякому разі, типи значень, що повертаються дають недостатньо відомостей компілятору С #, щоб вирішити, який саме метод слід використовувати.) Зрозуміло, що перевантажуються методи можуть відрізнятися і типами значень, що повертаються. Коли викликається перевантажується метод, то виконується той його варіант, параметри якого відповідають (за типом і кількістю) переданим аргументів.

Нижче наведено простий приклад, який демонструє перевантаження методів.

Ось до якого результату приводить виконання наведеного вище коду.

без параметрів
Один параметр: 2
Два параметра 4 6
Результат виклику методу ob.OvlDemo (4, 6): 10
Два параметра типу double: 1.1 2.32
Результат виклику методу ob.OvlDemo (1.1, 2.32): 3.42

Як бачите, метод OvlDemo () перевантажується чотири рази. Перший його варіант не отримує параметрів, другий отримує один цілочисельний параметр, третій - два цілочисельних параметра, а четвертий - два параметра типу double. Зверніть також увагу на те, що два перші варіанти методу OvlDemo () повертають значення типу void. а по суті, не повертають жодного значення, а два інших - повертають конкретне значення. І це абсолютно допустимо, але, як пояснювалося вище, тип значення не має ніякого значення для перевантаження методу. Отже, спроба використовувати два різних (по типу значення, що повертається) варіанту методу OvlDemo () в наведеному нижче фрагменті коду призведе до помилки.

І як пояснювалося в розділі 3, в C # передбачений ряд неявних (тобто автоматичних) перетворень типів. Ці перетворення поширюються також на параметри перевантажуються методів. Як приклад розглянемо наступну програму.

При виконанні цієї програми виходить наступний результат.

В даному прикладі визначені тільки два варіанти методу MyMeth (). з параметром типу int і з параметром типу double. Проте методу MyMeth () можна передати значення типу byte, short або float. Так, якщо цим методом передається значення типу byte або short, то компілятор C # автоматично перетворює це значення в тип int і в підсумку викликається варіант MyMeth (int) даного методу. А якщо йому передається значення типу float. то воно перетворюється в тип double і в результаті викликається варіант MyMeth (double) даного методу.

Слід, однак, мати на увазі, що неявні перетворення типів виконуються лише в тому випадку, якщо відсутня точна відповідність типів параметра і аргументу. Як приклад нижче наведена трохи змінена версія попередньої програми, в яку доданий варіант методу MyMeth (), де вказується параметр типу byte.

Виконання цієї програми призводить до наступного результату.

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

Обидва модифікатора параметрів, ref і out, також враховуються, коли приймається рішення про перевантаження методу. Як приклад нижче наведено фрагмент коду, в якому визначаються два абсолютно різних методу.

Отже, при зверненні

викликається метод MyMeth (int x), але при зверненні

викликається метод MyMeth (ref int x).

Незважаючи на те що модифікатори параметрів ref і out враховуються, коли приймається рішення про перевантаження методу, відмінність між ними не настільки істотно. Наприклад, два наступні варіанти методу MyMeth () виявляються неефективними.

В даному випадку компілятор не в змозі розрізнити два варіанти одного і того ж методу MyMeth () тільки на підставі того, що в одному з них використовується параметр out. а в іншому - параметр ref.

Перевантаження методів підтримує властивість поліморфізму, оскільки саме таким способом в C # реалізується головний принцип поліморфізму: один інтерфейс - безліч методів. Для того щоб стало зрозуміліше, як це робиться, звернемося до конкретного прикладу. У мовах програмування, що не підтримують перевантаження методів, кожному методу повинно бути присвоєно унікальне ім'я. Але в програмуванні часто виникає потреба реалізувати по суті один і той же метод для обробки різних типів даних. Припустимо, що потрібно функція, яка визначає абсолютне значення. У мовах, що не підтримують перевантаження методів, зазвичай доводиться створювати три або більше варіантів такої функції з дещо відмінними, але все ж різними іменами. Наприклад, в С функція abs () повертає абсолютне значення цілого числа, функція labs () - абсолютне значення довгого цілого числа, а функція fabs () - абсолютне значення числа з плаваючою точкою звичайної (одинарної) точності.

В С перевантаження не підтримується, і тому у кожної функції повинно бути своє, особливе ім'я, незважаючи на те, що всі згадані вище функції, по суті, роблять одне й те саме - визначають абсолютне значення. Але це принципово ускладнює становище, оскільки доводиться пам'ятати імена всіх трьох функцій, хоча вони реалізовані по одному і тому ж основному принципу. Подібні труднощі в C # не виникають, оскільки кожному методу, який визначає абсолютне значення, може бути присвоєно одне і те ж ім'я. І дійсно, до складу бібліотеки класів для середовища .NET Framework входить метод Abs (), який перевантажується в класі System.Math для обробки даних різних числових типів. Компілятор C # сам визначає, який саме варіант методу Abs () слід викликати, виходячи з типу переданого аргументу.

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

Коли метод перевантажується, кожен його варіант може виконувати яке завгодно дію. Для встановлення взаємозв'язку між перевантажуються методами не існує якогось одного правила, але з точки зору правильного стилю програмування перевантаження методів має на увазі подібний взаємозв'язок. Отже, використовувати один і той же ім'я для незв'язаних між собою методів не слід, хоча це і можливо. Наприклад, ім'я Sqr можна було б вибрати для методів, які повертають квадрат і квадратний корінь числа з плаваючою крапкою. Але ж це принципово різні операції. Таке застосування перевантаження методів суперечить її первісним призначенням. На практиці перевантажувати слід тільки тісно пов'язані операції.

У C # визначено поняття сигнатури. позначає ім'я методу і список його параметрів; Стосовно до перевантаження це поняття означає, що в одному класі не повинно існувати двох методів з однієї і тієї ж сигнатурою. Слід підкреслити, що в сигнатуру не входить тип значення, оскільки він не враховується, коли компілятор C # приймає рішення про перевантаження методу. У сигнатуру не входить також модифікатор params.

Схожі статті