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?
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
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) |
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
Ebben a cikkben bemutatjuk a metódusok alapjait. Nem érintjük viszont például a túlterhelést, ezt egy következő részben tekintjük át.. . . .
A sorozatunknak ebben a részében átnézzük általánosságban az osztályok alapjait egy konzolalkalmazás segítségével. A konstruktorok viszont a következő részben kerülnek bemutatásra.. . . .
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.. . . .