Változó paraméterszám kezelése
A függvények általában adott paraméterek kezelésére vannak tervezve. A formális paraméterlistában meg kell adni, hogy milyen típusú paramétereket várunk. A felsorolás megadja azok számát is (és nevét).
{
if (a>b) return a;
return b;
}
Ez a max függvény két int típusú paraméterrel dolgozik, és megadja a két érték közül a legnagyobb számértéket. Mi történik akkor, ha a projektben három értékkel dolgozó függvényre is szükség van.
Overloading szabály
Az overloading (túltöltés) szabály megengedi, hogy több ugyanazon nevű függvény is legyen a kódban, míg azok paraméterlistában egyértelműen különböznek. Ezért a három paraméteres max függvénynek is választhatjuk ugyanezt a nevet.
{
if (a>b && a>c) return a;
if (b>a && b>c) return b;
return c;
}
A hívás helyén megadott aktuális paraméterlista egyértelműen azonosítja melyik függvényt kell kiválasztani.
int n = max(m,67,12);
Nem minden programozási nyelv támogatja az overloading szabályt, egyes (régi) nyelveken tilos volt ugyanazon nevű függvényeket létrehozni. Ilyen a pascal. A Delphi ezt a korlátot kénytelen volt örökölni. Ugyanakkor a Delphi-ben már szabad azonos nevű függvényeket írni, de meg kell jelölni őket egy kulcsszóval jelezve a szándékosságot. Ennek hiányában a fordító hibát jelez (pascal kompatibilitás őrzése).
A C alapú nyelveken általában működik az overloading szabály. A PhP-ban például pont nem, de annak is van oka hogy miért nem, de ez most nem témája ennek a jegyzetnek.
Változó paraméterszám
Az overloading szabály mellett is vannak még problémák. Ha nem csak három, de négy, öt paraméteres max függvény is kell, akkor azokat is meg kell külön írni. Ha a projekt megköveteli, hogy akár 20 paraméteres változat is kell, akkor bizony annyi különböző változatot kell elkészíteni.
Ezt a problémát már csak a változó paraméterszámú függvények képesek kezelni. Ennek során jelezzük a fordítónak, hogy az adott függvénynek nem rögzített (fix) paraméterszáma van, hanem a hívás helyén tetszőleges sok (akár több száz) konkrét paraméterértéket is át szabad adni.
A paraméterlistában ezt a params kulcsszóval lehet jelölni. A tetszőlegesen sok paramétert ilyenkor egy vektorban kapjuk majd meg. A vektor alaptípusát meg kell adni.
{
if (t.Length==0) return 0;
int m = t[0];
for(int i=1;i<t.Length;i++)
{
if (t[i]>m) m=t[i];
}
return m;
}
Az params int[] t jelöli, hogy a hívás helyén tetszőlegesen sok int-et adhatnak meg, melyekből a rendszer automatikusan generál egy t vektort. A t vektor elemszáma egyezni fog az átadott int-ek számával. A függvénynek ezen vektorban lévő számokból kell kiválasztani a legnagyobbat.
int n = max(12);
int p = max();
A fenti függvényhívások mindegyike helyes. Első esetben három elemű lesz a függvény belsejében a t, második esetben csak 2 elemű. Harmadik hívás is helyes - nulla elemű lesz a t vektor. Ezért kellett a kód elején ezt az esetet kizárni.
Legalább egy paraméterű függvények
Ezzel el is értünk az első kezelendő problémához. Hogyan jelezzük, hogy a maximális elem kereséséhez legalább egy számra szükség van?
{
int m = elso;
for(int i=1;i<t.Length;i++)
{
if (t[i]>m) m=t[i];
}
return m;
}
Ez a változat tartalmaz egy fix paramétert. A továbbiakban tetszőleges sok int-et lehet megadni, melyek már a t vektorba kerülnek. Ezt a függvényt már nem lehet paraméter nélkül meghívni, de szabad egy paraméterrel. Ekkor ez az egy az elso változóba kerül, és a t vektor üres lesz.
Különböző típusú értékek
Amennyiben más-más a paraméterek típusa, ez a megoldás nehezen működik, hiszen a vektor alaptípusát meg kell adni. Ettől a hívás helyén sem szabad eltérni.
// error: argument '3' cannot convert double to int
Az sem lehetséges, hogy a params utáni vektor után még legyenek újabb paraméterek. E miatt két params sem lehet ugyanabban a függvényben:
static int max(int elso, params int[] t, double x) {...}
// ez is
static int max(int elso, params int[] t, params double[] x) {...}
Amennyiben vannak különböző típusú paramétereink, azokat a fix részen kell fogadni. A params már csak egyforma típusokkal képes együttműködni:
{
...
}
Megjegyzés: az OOP típuskompatibilitási szabályait ismerve lehet olyan típust találni, amely minden más típussal kompatibilis. Az object típus ilyen. Ilyen típusú értékek fogadása esetén a hívás helyére bármilyen típusú érték írható. Más kérdés, hogy az adatokkal való műveletvégzéshez a típusellenőrzés, típuskényszerítés, operátor overloading, késői kötés, és egyéb oop technikák ismeretére is valószínűleg szükség lesz:
{
...
}