A InfoWiki wikiből
WikiSysop (vita | szerkesztései)
(Új oldal, tartalma: „<cim cim3="THIS" cim2="Objektum-orientált programozás" cim1="Magasszintű Programozási Nyelvek II." prev="mp3/ea11" next="mp3/ea13" back="mp3/Nyitolap" ke...”)
Újabb szerkesztés →
Aktuális változat
Tartalomjegyzék |
THIS paraméter
A 'this' (más nyelveken 'self') kulcsszóval a példányszintű metódusokban (beleértve a példányszintű konstruktorokat is) hivatkozhatunk az aktuális példányra. Más szóval a 'this' hordozza az aktuális példány referenciáját.
Ezen 'this' egy láthatatlan paraméterként viselkedik példányszintű metódus esetében. Mintha minden metódus automatikusan megkapná azt egy extra paraméter formájában automatikusan, a hívás helyén megjelölt példány alapján:
class TAuto { protected int aktBenzin; public void Feltankol(int mennyiseg) { aktBenzin += mennyiseg; } } // ... főprogram ... TAuto a = new TAuto(); TAuto b = new TAuto(); a.Feltankol( 10 ); b.Feltankol( 15 );
A fenti kód valójában az alábbi formában létezik (a fordítóprogram automatikusan végzi az átalakítást):
class TAuto { protected int aktBenzin; public void Feltankol(int mennyiseg, TAuto this) { this.aktBenzin += mennyiseg; } } // ... főprogram ... TAuto a = new TAuto(); TAuto b = new TAuto(); TAuto -> Feltankol( 10, a ); TAuto -> Feltankol( 15, b );
Vagyis a példányszintű metódusok esetén a plusz egy paramétert automatikusan írja hozzá a formális paraméterlistához. A 'this' paraméter típusa megegyezik a szóban forgó osztály típusával.
A hívás helyén a példányt, amelyen keresztül a metódust meghívtuk, automatikusan helyezi el az aktuális paraméterlistában, hogy a 'this' paraméter értéke felvehesse annak referenciáját (memóriacímét).
Ha egy példányszintű metódusban valamely példányszintű mezőre hivatkozunk, akkor az elé automatikusan beíródik a 'this.' hivatkozás, jelezvén hogy ez az aktuális példány szóban forgó mezője kell legyen. Ezért lehetséges az, hogy az 'a.Feltankol(...)' esetében az 'a' példány 'aktBenzin' mezője módosul, míg második esetben a 'b' példány megfelelő mezője módosul, a nélkül hogy ezt a metódus belsejében különösebben jeleznünk kellene.
THIS és az osztályszintű metódusok
Ilyen extra paraméter az osztályszintű metódusok (és konstruktor) esetében nyilvánvalóan nincsen, hiszen ezen metódusok hívásához nincs szükség példányokra. A hívásuk osztálynéven keresztül történik meg, vagyis nincs példány, amely ezen extra paraméter értékét definiálhatná az aktuális paraméterlistában.
THIS felhasználása (1)
Mint láthatjuk, a 'this' a háttérben teljesen automatikusan, és logikusan működik, a programozó beavatkozására nincs szükség. Miért fontos akkor ennek ismerete?
Elsősorban azért, mert ez a magyarázata annak (többek között), hogy 'this' nevű paramétert a programozó nem deklarálhat a metódusaihoz. Ilyen nevű paraméter ugyanis már eleve létezik.
Másrészt ha a programozó tudatában van a 'this' létezésének és szerepének, akkor kihasználhatja azt. Elsősorban két esetben szoktuk hasznát venni a 'this' létezésének:
class TAuto { protected int kilometerAllas; public TAuto(int kilometerAllas) { // hibás! kilometerAllas = kilometerAllas; } } // ... főprogram ... TAuto a = new TAuto(0);
A fenti kód írásakor a programozó a konstruktor paraméterét ugyanúgy nevezte el, mint a mezőt. A konstruktor belsejében a paraméter értéket próbálja áttölteni a mezőbe, hogy megadja annak kezdőértékét, de ekkor a fordítóprogram már nem fogja érteni, melyik a mező, és melyik a paraméterváltozó név az értékadásban.
Az azonosítók újradeklarálásának szabálya szerint amennyiben egy azonosítót szűkebb érvényességi körrel újradeklarálunk, akkor ezen szűkebb területen ő elfedi a bővebb érvényességi körű azonosítót. A fenti példában a paraméterváltozó szűkebb érvényességi körű mint a mező, ezért a konstruktor belsejében mindkét 'kilometerAllas' azonosító a paraméterváltozót jelöli, vagyis az értékadó utasítás átmásolja a 'kilometerAllas' paraméterváltozó értékét a 'kilometerAllas' paraméterváltozóba. Ez nyilván "nem csinál semmit", értelmetlen és haszontalan, mindössze pár órajelet vesz el a processzortól.
Nyilvánvalóan a hibát a programozó követte el, aki ugyanúgy nevezte el a paraméterváltozót, mint a mezőt. Nyilvánvalóan a problémát megoldja az, ha másképp nevezi el a paraméterváltozót, mint a mezőt:
class TAuto { protected int fKilometerAllas; public TAuto(int kilometerAllas) { // helyes fKilometerAllas = kilometerAllas; } } // ... főprogram ... TAuto a = new TAuto(0);
A fenti névadási szokás egy időben jellemző volt a programozókra, a mezők nevét 'f'-el kezdték (f = field = mező). Ugyanakkor nincs szükség erre, ha a programozó ismeri és felhasználja a 'this' paramétert, amely már a példányszintű konstruktorok esetén is működik:
class TAuto { protected int kilometerAllas; public TAuto(int kilometerAllas) { // szintén helyes this.kilometerAllas = kilometerAllas; } } // ... főprogram ... TAuto a = new TAuto(0);
A fenti megoldásban a 'this.kilometerAllas' egyértelműen a mezőt jelöli, a 'this' nélküli második 'kilometerAllas' pedig továbbra is a paraméterváltozót. A fenti megoldással gyakran lehet találkozni, hiszen egyrészt a programozó mentesül, hogy eltérő névadást kelljen használnia, másrészt a 'this.' kiírása után a "Visual Studio" azonnal felsorolja a mezők (és metódusok) neveit listaszerűen, ezért használata bizonyos szempontból kényelmes is.
THIS felhasználása (2)
Míg az előző felhasználás nem szükségszerű, addig a most ismertetett felhasználás más módon, mint a 'this' használata - nem megoldható:
class Rendorseg { public static KarambolJelentes(TAuto a, TAuto b) { // az 'a' és 'b' autók karamboloztak, helyszinelés, stb. ... } } class Auto { public void Osszeutkozes(TAuto szembejovo) { if (sikerulKikerulni(szembejovo)==false) Rendorseg.KarambolJelentes(this, szembejovo); } } // .. főprogram .. TAuto a= new TAuto("IDE-321","Skoda",75); TAuto b= new TAuto("BOSS-001","BMW",140); a.Osszeutkozes(b);
A fenti kódban az látszik, hogy amikor az 'a' autónk összeütközés közelébe kerül
a 'b' autóval, és nem sikerül elkerülni a balesetet, akkor a rendőrség felé azonnal jelenti a karambolt. Ehhez azonban mindkét, a karambolban részt vevő autót azonosítani kell. Az egyik autó az rendben van, azt megkaptuk paraméterként, ő a 'szembejovo', a másik autó viszont saját magunk vagyunk. Saját magunkra pedig a 'this' segítségével hivatkozhatunk.
A fenti eset elég gyakori: a metódus belsejéből aktiválunk egy másik metódust, akinek
paraméterként át kell adni saját magunkat. Ekkor a 'this' használata nem elkerülhető!
A THIS további jelentései
Megjegyeznénk, hogy a fenti esetek a 'this' kulcsszó metódusok belsejében történő
felhasználási esetére vonatkozik.
De a 'this' kulcsszót használjuk akkor is, amikor egyik példányszintű konstruktorból
egy másik saját osztálybeli példányszintű konstruktort hívunk:
class Teglalap { public int X; public int Y; public int Szeles; public int Magas; public Teglalap():this(0,0,10,10) { } public Teglalap(int aX, int aY, int aSzeles, int aMagas) { X = aX; Y = aY; Szeles = aSzeles; Magas = aMagas; } }
Illetve 'this'-nek kell elneveznünk az indexelő propertyt is:
class String { public char this[int index] { get { // az 'index'-edik karakter visszaadása return .... ; } } }