Tanultunk arról, hogy egy osztályon belül lehetnek field-ek és metódusok is.
Ezen field-eket és metódusokat elérjük és tudjuk hivatkozni bármelyik az osztályon belüli metódusból. Viszont lehetséges, hogy egy másik osztályból szeretnénk hivatkozni a megadott függvényekre és változókra.
Erre láttunk példát a Összetett típusok tagmetódusai leckében. Vigyük tovább az ekkor ismertetett példát.
Tegyük fel hogy írok két osztályt egy játékhoz:
class LivingObject // Élettel (health) rendelkező és sebezhető osztály
{
public float health;
public Element element;
public float resistance;
public void TakeDamage(Damager damager)
{
if (element == damager.element)
{
health -= damager.damage * (1 - resistance);
}
else
{
health -= damager.damage;
}
if (health <= 0)
{
Console.WriteLine("Living Object Died");
}
}
}
Ezután így tudtunk sebzést elvégezni a egy LivingObject
és egy Damager
találkozásakor:
LivingObject livingObj =
new LivingObject {health = 100, element = Element.Fire, resistance = 0.75f};
Damager damager =
new Damager {damage = 100, element = Element.Fire};
// 3-szor megtörténik a sebzés:
livingObj.TakeDamage(damager);
livingObj.TakeDamage(damager);
livingObj.TakeDamage(damager);
Viszont semmi akadálya, hogy hibásan a következő kódot írja meg valaki, aki kevéssé van tisztában a LivingObject
sebzésének működésével:
livingObj.health -= damager.health; // 🛑 Ez így hibás, de futtatható 🛑
Ez nem a helyes módja a programunkban annak hogy Damager
sebezzen egy LivingObject
-et. Pont erre a feladatra írtuk meg a LivingObject
osztály TakeDamage
metódusát, aminek működése valamivel bonyolultabb, mint egy szimpla összeadás. Ennek ellenére semmi akadálya annak, hogy ezt a kódot lefuttassuk.
Elérhető viszont az, hogy a fenti hibás kód szintaktikai hibát adjon, ezzel elérve, hogy ne lehessen véletlenül rosszul használni a LivingObject
osztály sebzését.
Ennek módja az, hogy módosítjuk a LivingObject
health field-jének láthatóságát/elérhetőségét, úgy hogy elé nem a publi
c, hanem a private
kulcsszót írjuk.
Ebben az esetben az adott field csak osztályon belülről lesz közvetlenül hivatkozható. Kifelé nem fog lászódni, nem lesz elérhető.
Ugyanígy tudjuk szabályozni metódusok elérhetőségét is.
Ebben az esetben viszont nem fogjuk tudni szintán így létrehozni az LivingObject egy példányát:
LivingObject livingObj =
new LivingObject {health = 100, element = Element.Fire, resistance = 0.75f};
Helyette egy konstruktort kell használnunk. Lásd : Összetett típusok tagmetódusai - A konstruktor
A láthatóság módosítók
A public
kulcsszó egy Accessability modifier (láthatóság vagy elérhetőség módosító).
Ez ugyanúgy működik változók és metódusok elérésére is.
2 láthatóság módosítót tanulunk ezen a kurzuson (de több is létezik):
private
- Nem érhető az tag (field vagy metódus) az osztályon kívülről.
public
- Elérhető az tag (field vagy metódus) az osztályon kívülről.
Minden field vagy metódus alapértelmezetten private
, azért ennek a kulcsszónak a kiírása opcionális.
Javaslom is mindenkinek, hogy a private
kulcsszót ne írja ki. Áttekinthetőbb lesz így a kód.
Hosszú távon gondolkodjunk alapvetően minden tagról (fiel-ről és tagmetódusról) úgy, hogy mindaddig privátok, amíg valami jó okunk nincs publikussá tenni őket.
Önkorlátozás a programozásban
Feltehetjük a kérdést: Miért jó ez? Ha mindent public-ba állítunk, azt a metódust vagy osztályváltozót érjük el, amit csak szeretnénk. Miért ne tennénk így mindig, miért korlátoznánk magunkat le azzal, hogy elérhetetlenné teszünk programozási elemeket? És eleve miért a privát az alapértelmezett láthatóság? A C# miért nehezíti így meg feleslegesen az életünket?
Ezekre a kérdésekre talán az a válasz merülhet fel, hogy ez valamiféle eszköz a teljesítmény javítására és a privát metódusok végrehajtása talán gyorsabb a publikusaknál. Ez nem így van. Mindkettőt tökéletesen ugyanúgy hajtja végre a számítógép.
Vegyük a következő valós világ béli példát: Amikor veszünk egy új autót, akkor annak az összes alkatrészét a kormánytól az üléseken át a motor minden dugattyújáig birtokoljuk. Ezek közül a kormány, sebváltó, pedálok és a teljes műszerfal könnyedén hozzáférhető, hogy azt tegyünk vele, amit csak szeretnénk. Ezzel szemben motor és sok más belső alkatrész gondosan el van zárva tőlünk.
Minden jogunk megvan hozzá, hogy szétszedjük az akkumulátort, belenézzünk a karburátorba vagy módosítsuk a differenciálművet, elvégre megvettük az autót, az a miénk. Persze mindez nyilván nem lenne a legbölcsebb dolog, ha nem rendelkezünk magasszintű autószerelői ismeretekkel. Ha ez nem így van, könnyedén tönkre tehetjük a vadiúj autónkat.
Szóval az autó logikailag szétbontható két részre:
- Felhasználótól eltakart rész (Motor, karburátor, diferenciálmű …)
- Felhasználó számára elérhető rész: felhasználói felület ( Kormány, sebváltó, műszerfal …)
Az autó gyártója biztosít minket, hogy ha csak az előbbiekhez nyúlunk hozzá, akkor nem tudjuk tönkre tenni az autót. Ebben olyan biztos, hogy garanciát is nyújt a járműre. Ha viszont felnyitjuk a motorháztetőt és nekiállunk ott bütykölni, a garancia elvész.
Néha ugyan hozzá kell érni az eltakart részekhez is, de ha biztosak akarunk lenni, hogy nem teszünk tönkre valamit, jobb ha ezt egy hozzáértő szakember teszi.
Ugyanígy működik ez egy osztály esetében is. Ahogy az autók, úgy a programok is tudnak nagyon összetettek lenni. A láthatóság modosítókkal felbontható egy kód a következőképp:
- Belső működés - Kívülről NEM elérhető,
private
elemek - Interface, azaz felhasználói felület - Kívülről elérhető,
public
elemek
Amikor egy változó vagy metódus private
, azzal azt komunikáljuk a kollégánknak (vagy a két hét múlvai saját magunknak), hogy ehhez az elemhez jobb nem nyúlnod, ha azt szeretnéd, hogy jól működjön a program.
Ha viszont egy programozási elem publikus, akkor azzal azt jelzed, hogy különösebb extra körültekintés nélkül módosíthatók a változók, hívhatók a metódusok.
private
taghoz, és ezért módosítanád az láthatóságát public
-ra, annak nincs semmi akadálya, de előtta alaposan győződj meg róla, hogy mindent rendben csinálsz!Nézzük a kezdeti példánkat a sebezhető és a sebző osztállyal. A Player
osztályban privát a health
mező, de publikus a TakeDamage
metódus.
Ezáltal biztosítjuk, hogy a health
értéke sosem csökkenhet 0 alá, mivel a TakeDamage
metódus megírásánál figyeltünk erre. (Tételezzük fel, hogy ez nagyon fontos a programunk szempontjából.)
Ha viszont hozzáférne mindenki a health
field-hez, akkor nem lehetnénk benne biztosak, hogy mindenki úgy használja, ahogy kell.
Ez a fenti illusztráció igen egyszerű, révén csak egy iskolapélda. Egyszerűségénél fogva pedig nem érzékelteti igazán a accessability modifier-ek hasznosságát. Mikor majd jóval összetettebb kódokat kezdetek írni, akkor fogjátok igazán tapasztalni, mennyire hasznos eszköz is ez.
Kicsit olyan mintha ágyúval lőnénk egy verébre, és felmerülne a kérdés jogosan, hogy a csúzli miért nem volt elég. Akkor viszont amikor háborúba megyünk, nagy segítségünkre lesz ez az ágyú.