A InfoWiki wikiből
68. sor: | 68. sor: | ||
= Megosztott változók deklarálása = | = Megosztott változók deklarálása = | ||
- | Amennyiben | + | Amennyiben olyan változókra van szükségünk, amelyek közösek (megosztottak) a különböző alprogramok |
+ | között, azokat az alprogramokon kívül, de az osztályunk belsejében kell deklarálni. Ez esetben a ''static'' | ||
+ | kulcsszót is ki kell tenni a változóink deklarációja során. Ennek oka, hogy ezen változók a ''static'' | ||
+ | jelzőjű alprogramok között kerül megosztásra (részletesebb indoklása a következő félévben várható): | ||
+ | |||
+ | <code lang="csharp"> | ||
+ | class Program | ||
+ | { | ||
+ | static int a; | ||
+ | static void Egyik() | ||
+ | { | ||
+ | a=3; // a közös 'a' változónk | ||
+ | Masik(); // ő is ezt használja | ||
+ | Console.Write(a); // ezért itt már 4 lesz | ||
+ | ... | ||
+ | } | ||
+ | |||
+ | static void Masik() | ||
+ | { | ||
+ | ... | ||
+ | a++; // a közös 'a' változót növeljük | ||
+ | ... | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <box type="warn">Amennyiben ilyen megosztott változónk van, és azt egy alprogramban kívánjuk | ||
+ | használni, értéket tenni bele, vagy kiolvasni a benne szereplő értéket - akkor a változót | ||
+ | már '''az alprogramban tilos újra deklarálni'''. Amennyiben megtesszük, a frissen deklarált | ||
+ | változónk elfedi a külső, megosztott változót, és nem a kívánt eredményt érjük el.</box> | ||
+ | |||
+ | = Megosztott változók hatásköre = | ||
+ | |||
+ | A megosztott (osztály belsejében deklarált static változók) hatásköre a teljes osztályra kiterjed. | ||
+ | Tehát nem a deklaráció pontos helye a döntő (nem ettől a sortól kezdődik a hatásköre), hanem | ||
+ | az adott osztályban szereplő minden alprogramra kiterjed! | ||
+ | |||
+ | <code lang="csharp"> | ||
+ | class Program | ||
+ | { | ||
+ | static void Egyik() | ||
+ | { | ||
+ | a=3; // az 'a' hatásköre ide is kiterjed | ||
+ | Masik(); // ő is ezt használja | ||
+ | Console.Write(a); | ||
+ | ... | ||
+ | } | ||
+ | |||
+ | static int a; | ||
+ | |||
+ | static void Masik() | ||
+ | { | ||
+ | ... | ||
+ | a++; // és ide is | ||
+ | ... | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Ez a változók esetén nem így van, ott az attól a sortól kezdődik a hatáskör, ahol a változót | ||
+ | deklaráltuk, és a befoglaló kapcsos zárójelig tart. A megosztott változók hatásköre azonban | ||
+ | ''felfele'' is terjedhet, a teljes osztályt átfogja. | ||
+ | |||
+ | |||
+ | = A változók élettartama = | ||
+ | |||
+ | Egy ilyen ''static'' változó élettartama a teljes program futásának idejére kiterjed. | ||
+ | Vagyis mikorra a ''Main()'' függvényünk elindul, ez a változó már a memóriában van, és | ||
+ | amíg a program fut, végig ott is marad. Ezt az élettartamot '''statikus''' élettartamnak | ||
+ | (teljes futási idő) nevezzük. | ||
+ | |||
+ | Az alprogramok belsejében deklarált változók élettartama teljesen eltér ettől. Először | ||
+ | is csak akkor kerülhetnek be a memóriába, ha az adott alprogram elindul. Valamint amint | ||
+ | az alprogram befejeződik, a benne deklarált változók automatikusan kikerülnek (törlődnek) | ||
+ | a memóriából. Ezt '''dinamikus''' élettartamank nevezzük. | ||
+ | |||
+ | A dinamikus élettartam jellemzője, hogy amennyiben egy alprogramot többször is elindítunk, | ||
+ | minden induláskor a benne deklarált változók bekerülnek a memóriába, befejezésekor pedig | ||
+ | mindíg törlődnek. Ezért uyganaz az alprogram egymás utáni indítása során a korábbi | ||
+ | változóiba elhelyezett értékekhez ő maga sem tud már hozzáférni. Minden futása során | ||
+ | vadonatúj garnitúrával dolgozik. | ||
+ | |||
+ | A statikus élettartam rosszabb a memóriagazdálkodás szemszögéből. A változók végig a memóriában | ||
+ | vannak, végig foglalják a helyet. A dinamikus változók által foglalt memóriaterület futás közben | ||
+ | felszabadul, a helyükre más alprogramok változói kerülhetnek. Íly módon a memóriaterület | ||
+ | időben nem átfedő módon újrahasznosításra kerül. Ez természetesen takarékosabb. Ezért csak | ||
+ | azokat a változókat szoktuk statikus élettartamra tenni, amelyeknél ez indokolt! | ||
+ | |||
+ | <box note="info">A megosztott változók több szempontból is különböznek az alprogramokban | ||
+ | deklarált változóktól. Ezért a továbbiakban a nevük '''mező''' lesz (megkülönböztetésül). | ||
+ | Teljes nevük ''osztályszintű mező'', vagy ''statikus mező'', és az OOP félévben több | ||
+ | szempontból újra tárgyalásra kerülnek.</box> | ||
+ | |||
+ | = A mezők kezdőértéke = | ||
+ | |||
+ | A mezők abban is különböznek a változóktól, hogy kezdőértékkel rendelkeznek. A kezdőértékük | ||
+ | a típusukhoz illeszkedő ''nulla'' érték: | ||
+ | * egész számok esetén nulla | ||
+ | * tört számok esetén nulla egész nulla | ||
+ | * karakterek esetén a nulla kódú karakter | ||
+ | * logikai típus esetén a false | ||
+ | * string-ek esetén a null érték | ||
+ | |||
+ | A kezdőérték azt jelenti, hogy nem jelez ''definiálatlan változó'' hibát a fordító, ha | ||
+ | egy mező értéké kiolvassuk mielőtt a program abba értéket helyezett volna el: | ||
+ | |||
+ | |||
+ | <code lang="csharp"> | ||
+ | class Program | ||
+ | { | ||
+ | static int db; | ||
+ | static void Main() | ||
+ | { | ||
+ | db++; // ez nem hibás, 0-ról 1-re növelés | ||
+ | |||
+ | int a; | ||
+ | a++; // ez viszont hibás, 'a' nem definiált | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | A mezők értékét a változók kezdőértékéhez hasonló módon direkt (implicit) módon is beállíthatjuk | ||
+ | kezdőértékadás segítségével: | ||
+ | |||
+ | <code lang="csharp"> | ||
+ | class Program | ||
+ | { | ||
+ | static int legkisebb_prim = 2; | ||
+ | static string nev = "lajos"; | ||
+ | static void Main() | ||
+ | { | ||
+ | legkisebb_prim = 5; | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
= Más osztályok esete = | = Más osztályok esete = | ||
+ | |||
+ | Ha egy idegen (más) osztály mezőjére kívánunk hivatkozni, az alapvetően nem tehetjük meg, | ||
+ | csak ha ezt megengedjük. Az engedély kulcsszava itt is a ''public''. Ennek hiányában | ||
+ | a mezőre csak a saját osztályában lévő alprogramok hivatkozhatnak. A ''publikus mezők'' | ||
+ | esetén ebbe a mezőbe bármely (más) osztály alprogramjai is helyezhetnek értéket, kiolvashatják | ||
+ | a benne lévő értéket. Ekkor (hasonlóan mint az alprogramok esetén) ki kell írni a mezőt | ||
+ | tartalmazó osztály nevét is. | ||
+ | |||
+ | |||
+ | <code lang="csharp"> | ||
+ | class Sajat | ||
+ | { | ||
+ | static double d; | ||
+ | public static int x; | ||
+ | |||
+ | static void akarmi() | ||
+ | { | ||
+ | x = 23; // ezt szabad | ||
+ | d = 12.4; // itt ez is működik | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | class Program | ||
+ | { | ||
+ | static void Egyik() | ||
+ | { | ||
+ | Sajat.x = 12; // ez működik, public | ||
+ | Sajat.d = 23.4; // ez nem működik kívülről | ||
+ | .. | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
= Konstansok = | = Konstansok = | ||
+ | A helyzet a konstansokkal ugyanaz, mint a mezőkkel. A konstansok deklarálását jellemzően | ||
+ | az osztályok belsejében szoktuk elhelyezni. Ha a konstans értékét más osztályok is | ||
+ | kiolvashatják, akkor a ''public'' kulcsszóval erre engedélyt kell adni: | ||
+ | |||
+ | <code lang="csharp"> | ||
+ | class Math | ||
+ | { | ||
+ | public const double Pi = 3.1415927; | ||
+ | ... | ||
+ | } | ||
+ | |||
+ | class Program | ||
+ | { | ||
+ | static void Egyik() | ||
+ | { | ||
+ | double kerulet = 14.5*2*Math.Pi; | ||
+ | ... | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Vegyük észre, hogy a konstansok és a mezők kezdőértéke is beállítható, de a konstansok értékét | ||
+ | nem lehet módosítani, míg a mezőkét igen! | ||
+ | |||
+ | |||
+ | <code lang="csharp"> | ||
+ | |||
+ | class Program | ||
+ | { | ||
+ | const int labak_szama = 4; | ||
+ | static int fizetes = 1000000; | ||
+ | static void Egyik() | ||
+ | { | ||
+ | fizetes = fizetes+20000; // ezt lehet | ||
+ | labak_szama++; // HIBA: ezt nem | ||
+ | |||
+ | } | ||
+ | } | ||
+ | </code> | ||
<alairas>Hernyák Zoltán</alairas> | <alairas>Hernyák Zoltán</alairas> | ||
__NOTOC__ | __NOTOC__ |
A lap 2009. november 14., 12:57-kori változata
Megosztott változók
Amennyiben a programunkat több alprogramból áll, komoly kihívás előtt állunk. Az alprogramok egymás által kiszámolt értékekre hivatkoznak. Az egyik alprogramban kiszámolt értékeket egy másik alprogramban is fel kell használnunk. Sajnos, a változódeklaráció ekkor már kevés lesz! Ugyanis a változódeklaráció során valamely alprogramban deklarálunk egy változót, melynek hatásköre a befoglaló kapcsos zárójelen túl nem terjed - amely legjobb esetben is a befoglaló alprogram törzsének befejező kapcsos zárójele:
class Program { static void Egyik() { int a=3; // az 'a' valtozo hatáskörének kezdete ... } // és vége static void Masik() { ... a++; // HIBA: itt nem tudunk az 'a' változóra hivatkozni ... } }
Ezen az sem segít, ha a Masik() alprogramban is deklarálunk egy a nevű változót. Az ugyanis nem a fenti 'a' változót fogja jelölni, hanem egy másik változót.
class Program { static void Egyik() { int a=3; // a saját 'a' változónk Masik(); // ő egy másikat használ Console.Write(a); // a sajátunk még mindíg 3 ... } static void Masik() { ... int a=4; // ez itt egy másik 'a' változó ... } }
Megosztott változók deklarálása
Amennyiben olyan változókra van szükségünk, amelyek közösek (megosztottak) a különböző alprogramok között, azokat az alprogramokon kívül, de az osztályunk belsejében kell deklarálni. Ez esetben a static kulcsszót is ki kell tenni a változóink deklarációja során. Ennek oka, hogy ezen változók a static jelzőjű alprogramok között kerül megosztásra (részletesebb indoklása a következő félévben várható):
class Program { static int a; static void Egyik() { a=3; // a közös 'a' változónk Masik(); // ő is ezt használja Console.Write(a); // ezért itt már 4 lesz ... } static void Masik() { ... a++; // a közös 'a' változót növeljük ... } }
használni, értéket tenni bele, vagy kiolvasni a benne szereplő értéket - akkor a változót már az alprogramban tilos újra deklarálni. Amennyiben megtesszük, a frissen deklarált
változónk elfedi a külső, megosztott változót, és nem a kívánt eredményt érjük el.
Megosztott változók hatásköre
A megosztott (osztály belsejében deklarált static változók) hatásköre a teljes osztályra kiterjed. Tehát nem a deklaráció pontos helye a döntő (nem ettől a sortól kezdődik a hatásköre), hanem az adott osztályban szereplő minden alprogramra kiterjed!
class Program { static void Egyik() { a=3; // az 'a' hatásköre ide is kiterjed Masik(); // ő is ezt használja Console.Write(a); ... } static int a; static void Masik() { ... a++; // és ide is ... } }
Ez a változók esetén nem így van, ott az attól a sortól kezdődik a hatáskör, ahol a változót deklaráltuk, és a befoglaló kapcsos zárójelig tart. A megosztott változók hatásköre azonban felfele is terjedhet, a teljes osztályt átfogja.
A változók élettartama
Egy ilyen static változó élettartama a teljes program futásának idejére kiterjed. Vagyis mikorra a Main() függvényünk elindul, ez a változó már a memóriában van, és amíg a program fut, végig ott is marad. Ezt az élettartamot statikus élettartamnak (teljes futási idő) nevezzük.
Az alprogramok belsejében deklarált változók élettartama teljesen eltér ettől. Először is csak akkor kerülhetnek be a memóriába, ha az adott alprogram elindul. Valamint amint az alprogram befejeződik, a benne deklarált változók automatikusan kikerülnek (törlődnek) a memóriából. Ezt dinamikus élettartamank nevezzük.
A dinamikus élettartam jellemzője, hogy amennyiben egy alprogramot többször is elindítunk, minden induláskor a benne deklarált változók bekerülnek a memóriába, befejezésekor pedig mindíg törlődnek. Ezért uyganaz az alprogram egymás utáni indítása során a korábbi változóiba elhelyezett értékekhez ő maga sem tud már hozzáférni. Minden futása során vadonatúj garnitúrával dolgozik.
A statikus élettartam rosszabb a memóriagazdálkodás szemszögéből. A változók végig a memóriában vannak, végig foglalják a helyet. A dinamikus változók által foglalt memóriaterület futás közben felszabadul, a helyükre más alprogramok változói kerülhetnek. Íly módon a memóriaterület időben nem átfedő módon újrahasznosításra kerül. Ez természetesen takarékosabb. Ezért csak azokat a változókat szoktuk statikus élettartamra tenni, amelyeknél ez indokolt!
deklarált változóktól. Ezért a továbbiakban a nevük mező lesz (megkülönböztetésül). Teljes nevük osztályszintű mező, vagy statikus mező, és az OOP félévben több
szempontból újra tárgyalásra kerülnek.
A mezők kezdőértéke
A mezők abban is különböznek a változóktól, hogy kezdőértékkel rendelkeznek. A kezdőértékük a típusukhoz illeszkedő nulla érték:
- egész számok esetén nulla
- tört számok esetén nulla egész nulla
- karakterek esetén a nulla kódú karakter
- logikai típus esetén a false
- string-ek esetén a null érték
A kezdőérték azt jelenti, hogy nem jelez definiálatlan változó hibát a fordító, ha egy mező értéké kiolvassuk mielőtt a program abba értéket helyezett volna el:
class Program { static int db; static void Main() { db++; // ez nem hibás, 0-ról 1-re növelés int a; a++; // ez viszont hibás, 'a' nem definiált } }
A mezők értékét a változók kezdőértékéhez hasonló módon direkt (implicit) módon is beállíthatjuk kezdőértékadás segítségével:
class Program { static int legkisebb_prim = 2; static string nev = "lajos"; static void Main() { legkisebb_prim = 5; } }
Más osztályok esete
Ha egy idegen (más) osztály mezőjére kívánunk hivatkozni, az alapvetően nem tehetjük meg, csak ha ezt megengedjük. Az engedély kulcsszava itt is a public. Ennek hiányában a mezőre csak a saját osztályában lévő alprogramok hivatkozhatnak. A publikus mezők esetén ebbe a mezőbe bármely (más) osztály alprogramjai is helyezhetnek értéket, kiolvashatják a benne lévő értéket. Ekkor (hasonlóan mint az alprogramok esetén) ki kell írni a mezőt tartalmazó osztály nevét is.
class Sajat { static double d; public static int x; static void akarmi() { x = 23; // ezt szabad d = 12.4; // itt ez is működik } } class Program { static void Egyik() { Sajat.x = 12; // ez működik, public Sajat.d = 23.4; // ez nem működik kívülről .. } }
Konstansok
A helyzet a konstansokkal ugyanaz, mint a mezőkkel. A konstansok deklarálását jellemzően az osztályok belsejében szoktuk elhelyezni. Ha a konstans értékét más osztályok is kiolvashatják, akkor a public kulcsszóval erre engedélyt kell adni:
class Math { public const double Pi = 3.1415927; ... } class Program { static void Egyik() { double kerulet = 14.5*2*Math.Pi; ... } }
Vegyük észre, hogy a konstansok és a mezők kezdőértéke is beállítható, de a konstansok értékét nem lehet módosítani, míg a mezőkét igen!
class Program { const int labak_szama = 4; static int fizetes = 1000000; static void Egyik() { fizetes = fizetes+20000; // ezt lehet labak_szama++; // HIBA: ezt nem } }