WebElektronika

Metódusok túlterhelése a C# nyelvben

person access_time 2014.01.20.
Ebben a cikkben nem csak a metódusok túlterhelését nézzük meg egy konkrét példa segítségével, hanem szóba kerülnek a generikusok is, szintén egy kisebb projekt keretén belül.


Ebben a részben azt nézzük meg, hogy mit jelent az obejktumorientált nyelvekben a túlterhelés. A metódusok túlterhelésével találkozhatunk a C++, a Java nyelekben, de a C# nyelvben is megtaláljuk.

Indítsuk el a VS2012 fejlesztőrendszert, és a File/New/Project menüablakban válasszuk ki a "Console Application"-t. Adjunk a leendő projektünknek egy nevet (pl.: ConsoleMetodusTulterheles1) és mentsük el.

A "Program" osztályban jelenleg csak a Main metódust látjuk. Írjunk egy metódust, amely int-et ad vissza, illetve a bemenő két paraméter szintén int típusú. Legyen tehát egy olyan eljárásunk, ahol két egészet adunk össze, tehát az eredmény is int lesz.

A kapott kódunk (Program.cs) ilyen lesz : 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleMetodusTulterheles1
{
    class Program
    {
        static int Osszead(int a, int b)
        {
            return a + b;
        }      
        static void Main(string[] args)
        {
            Console.WriteLine("Az összeadás értéke : {0}", Osszead(10,20));
            Console.ReadLine();
        }
    }

}

Amikor ezt a kódot elindítjuk (pl.: F5 megnyomása), elindul a Main metódus, a Console osztály WriteLine metódusa meghívásra kerül. Emiatt szintén meghívásra kerül az "Osszead" metódusunk. Ennek a visszatérési értéke (10 + 20) lesz. A Main nem ér véget, mert várunk az Enter leütésére.

Igen ám, de most szeretnénk összeadni két double tpusú számot. Legyen a metódusunk neve akkor Osszead2? Vagy adjunk össze int és double vagy double és int típusú számokat. Az új metódusaink nevei legyenek Osszead3 és Osszead4?
 

Túlterhelés

A metódusok nevei megegyeznek (jelen esetben Osszead), de a szignatúrájuk különböznek (egyformák nem lehetnek). Ekkor beszélünk túlterhelésről. Tehát, ha szeretnénk olyan metódusokat készíteni, amely összead két int-et, int-et és double-t, double-t és int-et, illetve két double típusú számot, akkor nem kell négy különböző nevű metódust készítenünk, hanem, igaz négy metódus kell, de ezeknek elég ugyanaz a név is (Osszead).

Egészítsük ki az előbb közölt kódunkat a következőképpen.

class Program
    {
        static int Osszead(int a, int b)
        {
            return a + b;
        }
        static double Osszead(double a, int b)
        {
            return a + b;
        }
        static double Osszead(int a, double b)
        {
            return a + b;
        }
        static double Osszead(double a, double b)
        {
            return a + b;
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Az összeadás értéke : {0}",Osszead(10,20));
            Console.ReadLine();
        }
    }

Látjuk, hogy négy Osszead nevű metódusunk van, de a szignatúrájuk különböznek. Olyan nem lehet, hogy megegyezik a két metódus "fejléce", hiszen akkor a fordító nem tudná megkülönböztetni ezt a két metódust.

Vegyük észre azt, amikor írjuk az Osszead metódust nevét, akkor az IntelliSense felkínálja a metódusunk nevét, de megmutatja azt is, hogy a Program osztályban lévő Osszead nevű metódusnak +3 túlterhelése van (1. ábra).


1. ábra   Osszead metódus túlterhelése
 

Írjuk ki a metódusunk nevét (Osszead). Ekkor láthatjuk a következő IntelliSense ábrát (2.), ahol legördülő menüpont segítségével akár kiválaszthatjuk, melyik Osszead nevű metódust kívánjuk felhasználni. Természetesen, nem kötelező ezt kiválasztani, hiszen amikor a paraméterlistában megadjuk a két számot, akkor a fordító eldönti ezt helyettünk.


2. ábra   Osszead metódus túlterhelésének kiválasztása
 

Csak a saját metódusainkat tudjuk túlterhelni? A .NET keretkörnyezetben található "hivatalos" metódusoknál van a túlterhelésre lehetőségünk?
A válasz az, hogy igen, bármilyen metódus túlterhelhető, nem csak a mi általunk írt metódusok terhelhetők túl. Nézzük meg a Console osztály WriteLine metódusát (3. ábra). Összesen 19 lehetőségünk van.


3. ábra   Console.WriteLine túlterhelése
 

Generikusok

Látható a korábbi példán, hogy egy funkció megvalósítására felhasználtunk négy különböző szignatúrájú (prototípusú), de megegyező nevű metódust (túlterhelés), és a metódusok belseje megegyezik. Joggal merülhet fel a kérdés az Olvasóban, hogy ez a négy metódus kiváltható-e egy metódussal?

Igen, kiváltható, nézzük is meg a következő táblázatot :

a két paraméter (a, b) típusa megegyezik (T) a két paraméter (a, b) típusa különbözik
  double Kivon<T>(T a, T b)
  {
       return Convert.ToDouble(a) - Convert.ToDouble(b);
  }

   double Szoroz<T1, T2>(T1 a, T2 b)
   {
       return Convert.ToDouble(a) * Convert.ToDouble(b);
   }

Készítsünk el egy új projektet, ahol szorozni és kívonni szeretnénk. A kivonást csak egy típusú számpárnál  (pl.: int-int, double-double) szeretnénk megvalósítani, a szorzás műveletét különböző típusokra is szeretnénk implementálni.

A mintakód látható a következő sorokban.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleMetodusGenerikus1
{
    class Program
    {
        static double Kivon<T>(T a, T b)
        {
            return Convert.ToDouble(a) - Convert.ToDouble(b);
        }

        static double Szoroz<T1, T2>(T1 a, T2 b)
        {
            return Convert.ToDouble(a) * Convert.ToDouble(b);
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Kivonás : {0}:", Kivon(34,12));
            Console.WriteLine("Szorzás : {0}:", Szoroz(34, 23.4));
            Console.ReadLine();
        }
    }
}

Látható, hogy a két eljárás törzsében átalakítjuk a meghíváskor átadott paramétereket double típussá. Az aritmetikai művelet elvégzése után az eredményt (amely double) a return segítségével visszaadjuk.

Ezeket a metódusok meghívhatók úgy, hogy nem írjuk ki a típus(okat), hanem ezt a fordítóra bízzuk, de akár mi is meghívhatjuk úgy ezeket az eljárásokat, hogy a típusokat mi adjuk meg (4. ábra). 


4. ábra   Generikus metódusok meghívásának lehetőségei

 

A futási eredmény (5. ábra).


5. ábra   Futási eredmény