Strona główna » Kursy » Kurs C# » Przeciążanie Funkcji
 

Przeciążanie Funkcji

Wstęp

Przeciążanie funkcji to technika większości języków wysokiego programowania. Pozwala ona zapisać wiele funkcji pod jedną wspólną nazwą tak, aby funkcja mogła przyjmować argumenty różnego typu i odpowiednio dostosować swoje działanie.

Opis Przeciążeń

Kilka funkcji może mieć tą samą nazwę pod warunkiem, że różnią się sygnaturą. Do sygnatury funkcji należą:

Należy pamiętać, że do sygnatury nie należy typ wartości zwracanej, ani nazwy argumentów. Oznacza to, że dany zestaw argumentów może zwracać jeden konkretny typ wyniku. Z kolei nazwy argumentów mogą być dowolne.

Implementacja

Sumowanie liczb

Jednym z przykładów gdzie przeciążanie funkcji ma zastosowanie jest funkcja Sumuj(). Jak wiadomo jest wiele różnych typów zmiennych, które mogą przechowywać wartości liczbowe. Często się o tym zapomina, ponieważ kompilatory potrafią po cichu przekonwertować odpowiednie typy danych tak, aby były tego samego typu i żadne dane nie zostały utracone.

Jednak nie trzeba polegać na implementacjach wbudowanych w język programowania. Przypuśćmy, że chcemy napisać funkcję Sumuj(), która będzie służyła do dodawania dwóch argumentów typu int lub double. Zakładamy, że wartość rzczywista ma zostać zwrócona tylko, gdy oba argumenty są rzeczywiste ( w pozostałych wynikiem ma być liczba całkowita).

Pierwsze dwie definicja dotyczą pary argumentów takiego samego typu. Tutaj nie ma potrzeby, aby dokonywać dodatkowej konwersji argumentów.

  1. static int Sumuj(int a, int b) {
  2.   return a + b;
  3. }
  1. static double Sumuj(double a, double b) {
  2.   return a + b;
  3. }

Teraz pozostaje dopisać definicję, gdy argumenty są różnych typów. Tu należy z kolei pamiętać, że para argumentów int×double jest inna niż double×int, więc będzie trzeba napisać dwie definicje.

  1. static int Sumuj(int a, double b) {
  2.   return a + (int)(b);
  3. }

Z kolei kolejne przeciążanie możemy napisać tak, aby odwoływało się do poprzednio napisanego. Jest to przydatne w sytuacjach, gdy definicja funkcji zawiera bardzo dużo instrukcji.

Testowanie rozwiązania

W celu potwierdzenia poprawności działania warto napisać fragment kodu testującego, który wypisze wyniki

  1. static void Main(string[] args) {
  2.   int c1 = 3, c2 = 2;
  3.   double d1 = 3.14, d2 = 5.7;
  4.   Console.WriteLine("{0} + {1} = {2}", c1, c2, Sumuj(c1, c2));
  5.   Console.WriteLine("{0} + {1} = {2}", d1, c2, Sumuj(d1, c2));
  6.   Console.WriteLine("{0} + {1} = {2}", c1, d2, Sumuj(c1, d2));
  7.   Console.WriteLine("{0} + {1} = {2}", d1, d2, Sumuj(d1, d2));
  8.   Console.ReadKey();
  9. }

W kodzie zostały zadeklarowane po dwie zmienne typu int oraz double, a program wypisuje wynik dla każdej możliwej pary typów i zostały otrzymane następujące wyniki:

  1. 3 + 2 = 5
  2. 3,14 + 2 = 5
  3. 3 + 5,7 = 8
  4. 3,14 + 5,7 = 8,84

Jak można zauważyć program poprawnie wybiera przeciążenie i tylko dla liczb rzeczywistych double jest zwracana wartość rzeczywista, a w pozostałych przypadkach zostaje ucięta.

Wczytywanie danych

Innym zastosowaniem przeciążeniem może być funkcja wczytująca. Otóż jak wiadomo do sygnatury nie należy zwracany typ, więc nie jest możliwe, aby jedno polecenie Wczytaj() zwracało raz tekst, a raz liczbę całkowitą. Istnieje możliwość skorzystania z modyfikatora out argumentu, który pozwoli komputerowi odróżnić co ma zostać wczytane.

Pierwsza definicja funkcji Wczytaj() służy do wczytywania liczb całkowitych.

  1. static void Wczytaj(out int a) {
  2.   string dane = Console.ReadLine();
  3.   a = Convert.ToInt32(dane);
  4. }

Druga definicja funkcji posłuży do wczytania z konsoli liczby rzeczywistej. Warto zwrócić uwagę, że obie funkcje nie zwracają nic, ponieważ stosowany jest modyfikator out.

  1. static void Wczytaj(out double a) {
  2.   string dane = Console.ReadLine();
  3.   a = Convert.ToDouble(dane);
  4. }

Teraz pozostje sprawdzic poprawność działania obu funkcji poprzez wczytanie dwóch wartości, a następnie ich wypisania. Posłuży do tego następujący kod:

  1. static void Main(string[] args) {
  2.   int a;
  3.   Console.Write("a = ");
  4.   Wczytaj(out a);
  5.   double b;
  6.   Console.Write("b = ");
  7.   Wczytaj(out b);
  8.   Console.WriteLine("\n-- Wczytano --");
  9.   Console.WriteLine("a = {0}, b = {1}", a, b);
  10.   Console.ReadKey();
  11. }

Wynikiem działania programu dla a = 5 i b = 3.14 będzie wypisanie następującej informacji:

  1. -- Wczytano --
  2. a = 5, b = 3,14

Zadania

Zadanie 1

Napisz funkcję Sumuj(), która będzie mogła przyjmować dwa lub trzy argument każdy typu int. Wynikiem działania funkcji ma być suma wszystkich podanych argumentów.

Zadanie 2

Napisz funkcję Suma(), która pozwoli dodać do siebie dwie liczby całkowite z czego jedna jest zapisana jako tekst w zmiennej typu string. W obu przypadkach wynikiem działania funkcji ma być zmienna typu int.

Zadanie 3

Napisz funkcję Odwróć(), która jeśli wczyta liczbę typu int to zapisze ją wspak. Z kolei dla liczb rzeczywistych typu double zostanie zapisana wspak część całkowita oraz ułamkowa. Przyjmujemy w tym drugim przypadku, że liczba może mieć do trzech miejsc po przecinku.

Oto przykładowe wyniki:

  1. Odwróć(12) = 21
  2. Odwróć(345) = 543
  3. Odwróć(12,21) = 21,12
  4. Odwróć(456,123) = 654,321