Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка - Основи Програмування C_.doc
Скачиваний:
46
Добавлен:
18.12.2018
Размер:
1.44 Mб
Скачать

Перевантаження методів в мові с#.

1. Перевантаження методів.

Мова С# дозволяє реалізувати цікаву можливість при створенні методів – різні за змістом методи можуть мати однакові ідентифікатори. Ця технологія називається перевантаженням (overloading) методів. В програмуванні вживається термін «сигнатура методу» – сигнатура включає ідентифікатор методу та список його параметрів. Перевантаження дозволене для методів з різними сигнатурами. Тобто два або більше методів можуть мати однакові ідентифікатори при умові, що їх списки параметрів різняться або кількістю, або типами, або і тим, і іншим. Зверніть увагу, що результат, який повертається методом, до сигнатури не включається, отже, при перевантаженні методам недостатньо мати відмінності лише в типі результату. Якщо виникає питання про корисність такої можливості, то зауважимо, що однією із поширених студентських помилок при використання стандартної функції мови С++ для обчислення модуля числа є виклик функції abs(x), що повертає ціле значення модуля цілого числа x, в той час, коли необхідне звертання до функції fabs(x) з дійсними аргументом та результатом. А якщо згадати, що є ще функція labs(x) з довгим цілим результатом… Зрозуміло, що значно корисніше було б мати методи однакового призначення з однаковими ідентифікаторами для різних типів параметрів.

Розглянемо приклад, в якому перевантажені 4 методи MyMethod – з параметрами типів int, float, double та з двома цілими параметрами.

using System;

namespace Overloading

{

class Program

{// В цьому класі перезавантажуються методи

public void MyMethod (int x)

{

Console.WriteLine("Метод з цiлим параметром x = {0}", x);

}

public void MyMethod(float x)

{

Console.WriteLine("Метод з дiйсним параметром x ={0}",x);

}

public void MyMethod(double x)

{

Console.WriteLine(

"Метод з параметром подвоєної точностi x = {0}", x);

}

public void MyMethod(int x, int y)

{

Console.WriteLine("Метод з двома цiлими параметрами

x = {0} y = {1}", x, y);

}

static void Main()

{

Program pr = new Program();

pr.MyMethod(1);

pr.MyMethod(1.5);

pr.MyMethod(2.5F);

pr.MyMethod(1, 2);

}

}

}

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

Метод з цiлим параметром x = 1

Метод з параметром подвоєної точностi x = 1,5

Метод з дiйсним параметром x = 2,5

Метод з двома цiлими параметрами x = 1 y = 2

Виникає слушне питання, а що коли методу передається параметр, наприклад, цілий, але не int? Спробуємо виконати виклик функції MyMethod наступним чином:ї

byte b = 8;

pr.MyMethod(b);

Одержимо наступний результат:

Метод з цiлим параметром x = 8

Тобто викликається метод MyMethod (int x). Компілятор намагається підібрати серед методів, які перевантажуються, той, що найкращим чином відповідає фактичному аргументу (в даному разі типу byte) згідно правил приведення типів. Тому наступні звертання до методу MyMethod

pr.MyMethod(100L);

pr.MyMethod('A');

призведуть до цілком очікуваних наступних повідомлень:

Метод з дiйсним параметром x = 100

Метод з цiлим параметром x = 65

Тобто при першому виклику відбувається приведення фактичного аргументу до найближчого типу float, а у другому випадку тип char приводиться до типу int, і ми бачимо на екрані код символу 'A'.

Проте спроба виклику pr.MyMethod(1.1, 2.2); призведе до синтаксичної помилки, оскільки найбільш відповідним методом для цього виклику компілятор вважатиме MyMethod(int x, int y), але не матиме можливості виконати неявне приведення фактичних аргументів типу double до типу int.

Додамо тепер ще один метод MyMethod у клас Program:

public void MyMethod(ref int x)

{

x++;

Console.WriteLine("Метод з цiлим параметром

ref x = {0}", x);

}

Він теж має один параметр типу int , проте цей параметр використовується із модифікатором ref. Перевіримо, чи відрізнятиме компілятор сигнатури двох перевантажених методів MyMethod (int x) та MyMethod(ref int x). Внаслідок звертання

int i = 1;

pr.MyMethod(ref i);

одержимо результат Метод з цiлим параметром ref x = 2. Тобто модифікатори ref та out також впливають на сигнатури методів у випадку їх перевантаження. Але дуже важливо зауважити, що методи, які різняться лише модифікаторами ref та out, компілятор не зможе перевантажити. Для ілюстрації спробуємо додати ще один метод MyMethod у клас Program:

public void MyMethod(out int x)

{

x = 100;

Console.WriteLine("Метод з цiлим параметром

out x = {0}", x);

}

Результатом компіляції буде повідомлення про помилку:

«MyMethod» cannot define overloaded methods that differs only on ref and out

неможливо перевантажити методи, які розрізняються лише ref та out.

В той же час визначення та використання методу

public void MyMethod(out float x)

{

x = 100;

Console.WriteLine("Метод з дiйсним параметром

out x = {0}", x);

}

буде цілком успішним, адже два методи MyMethod(float x) та MyMethod(out float x) компілятор вважатиме «достатньо різними» і матиме можливість їх перевантаження.