fel
le

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).

static int max(int a, int b)
{
  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.

static int max(int a, int b, int c)
{
  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 m = max(12,46);
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.

static int max(params int[] t)
{
  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 m = max(12,15,56);
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?

static int max(int elso, params int[] t)
{
  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.

int m = max(12, 14, 15.6);
// 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:

// ez hibás
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:

static void feldolgoz(string s,double d,string m,bool b,params int[] t)
{
 ...
}
 

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:

static void barmitFogad(params object[] t)
{
 ...
}
 
Hernyák Zoltán
2013-01-24 17:51:52