C# esetén több azonos nevű metódust is létrehozhatunk egy osztályon belül. Ezt nevezzük többalakúságnak, vagyis polimorfizmusnak, mivel egy metódus többféleképpen is dolgozhat. A megkötés annyi, hogy az egyes metódusoknak jól megkülönböztethetÅ‘nek kell lenniük. A megkülönböztetés az argumentumok számában és tÃpusában kell, hogy megmutatkozzon. Ez talán egy példán keresztül érthetÅ‘bb:
public double Oszt(double p1, double p2)
{
return p1 / p2;
}
public int Oszt(double p1, double p2)
{
return (int)(p1 / p2);
}
var x = Oszt(2, 1);
Ez a kódrészlet fordÃtási hibát fog eredményezni. Ennek az oka az, hogy azonos a függvények neve és a paraméter listája is, csupán a visszatérési tÃpusban van különbség. EbbÅ‘l adódóan lényegében ellentmondásos definÃciót adunk a metódusról. A kód viszont már fordul, ha a második metódusunk paraméter listája eltér:
static double Oszt(double p1, double p2)
{
return p1 / p2;
}
static int Oszt(int p1, int p2)
{
return p1 / p2;
}
Viszont jelen példa egy kicsit problémás. A problémát az alábbi kódrészlet szemlélteti:
namespace PeldaMetodusok
{
class Program
{
static double Oszt(double p1, double p2)
{
return p1 / p2;
}
static int Oszt(int p1, int p2)
{
return p1 / p2;
}
static void Main(string[] args)
{
var elso = Oszt(3, 4);
var masodik = Oszt(3.0, 4.0);
Console.WriteLine(elso);
Console.WriteLine(masodik);
Console.ReadKey();
}
}
}
A program kimenete:
0
0,75
Az elsÅ‘ változó tÃpusa egész, int lesz, mivel a 3 és 4 számjegyeket int tÃpusként értelmezi a fordÃtó. A második változó esetén a tÃpus már lebegÅ‘pontos double lesz, mivel a 3.0 kifejezést már lebegÅ‘pontosnak fordÃtja a program. A helyzeten az sem segÃtene, ha explicit módon az elsÅ‘ változó tÃpusa double lenne, mivel a függvény hÃvást a paraméter listából találja ki a fordÃtó.
A fenti példákból leszűrhetÅ‘, hogy a polimorfizmus hasznos. Ha nem lenne, akkor a Convert osztály függvényeit nem lehetett volna ilyen univerzálisan megvalósÃtani. Viszont az is leszűrhetÅ‘, hogy tervezésekor és kódoláskor ügyelni kell arra, hogy a metódusok paraméter listájából egyértelműen azonosÃtható legyen, hogy melyik metódus fog végrehajtódni.
Ilyen szempontból a fenti példa nem a legjobb, viszont könnyen orvosolható a probléma. Jelen esetben úgy, hogy az egész visszatérési tÃpusú metódust eltávolÃtjuk, mivel explicit konverzióval a double tÃpus konvertálható egészre. Továbbá a metódus eltávolÃtása mellett szól az is, hogy az osztás igen ritkán produkál egész eredményt.
Ennek a fajta polimorfizmusnak több neve is ismert: korai kötésű, fordÃtás idejű, vagy statikus polimorfizmus. A polimorfizmus egy másik változata a
kései kötésű, futás idejű vagy dinamikus polimorfizmus néven ismert. Ez öröklés esetén alkalmazható. Ezt majd az öröklés ismertetése után tárgyaljuk.
Részleges metódusok
A részleges metódus csak részleges osztályban szerepelhet, nem rendelkezhet elérés módosÃtóval, ebbÅ‘l kifolyólag mindig private lesz az elérési szintje. Visszatérési értéke csak void lehet.
ElsÅ‘ hangzásra furcsa lehet a részleges metódus fogalma, mivel azt gondolnánk, hogy olyan függvény, amelynek kódja több forrásfájlon nyúlik át. Ennek nem sok értelme lenne, mivel fordÃtásilag nem lehetne eldönteni, hogy melyik kódrészlet jön hamarább. Ezért a részleges metódus úgy van megvalósÃtva, hogy az egyik forrás fájlban definiálva van a metódus névvel, a másik forrásfájlban pedig meg van valósÃtva a tényleges működése.
Ténylegesen szerepe ennek is a generált és felhasználó által Ãrt kód közötti elválasztásban van. Az alábbi példa a részleges osztályok és részleges metódusok használatát mutatja be:
using System;
namespace PeldaReszlegesMetodus
{
partial class Reszleges
{
partial void Metodus();
public Reszleges()
{
Metodus();
}
}
class Program
{
static void Main(string[] args)
{
Reszleges r = new Reszleges();
Console.ReadKey();
}
}
}
A reszleges.cs fájl tartalma:
using System;
namespace PeldaReszlegesMetodus
{
partial class Reszleges
{
partial void Metodus()
{
Console.WriteLine("Ez másik CS fájlban van :)");
}
}
}
A program kimenete:
Ez másik CS fájlban van :)