12. A java.lang és a System névtér alapvető osztályai
Ahhoz, hogy hatékonyan programozzunk objektumorientált környezetben, ismernünk kell a nyelvünk beépített alaptípusait és azok működését. A Java esetében ezeket az osztályokat a java.lang csomag, míg a C# esetében a System névtér tartalmazza.
1. A Mindenek Őse: Az Object osztály
Mind a Java-ban, mind a C#-ban létezik egy legfelsőbb ősosztály, amelyből (közvetve vagy közvetlenül) minden más osztály származik. Ez a Java-ban a java.lang.Object, a C#-ban pedig a System.Object.
Mivel ez a közös ős, a benne definiált metódusokat minden saját osztályunk megörökli. A legfontosabbak, amelyeket saját osztályainkban gyakran felül is definiálunk (override):
-
ToString()/toString(): Visszaadja az objektum adatait szöveges formában. Alapértelmezésben a C#-ban az osztály nevét, Java-ban pedig az osztály nevét és a memóriacímet (hash kódot) adja vissza, ezért saját osztályoknál mindig érdemes felülírni, hogy az objektum tényleges adatait (pl. egy ember nevét és korát) adja vissza. -
Equals(Object)/equals(Object): Két objektum összehasonlítására szolgál. Alapértelmezésben csak azt vizsgálja, hogy a két referencia ugyanarra a memóriacímre mutat-e. Ha tartalmi egyezőséget akarunk vizsgálni (pl. két különböző memóriacímen lévő, de azonos nevű és azonosítóval rendelkező ember egyenlő-e), akkor felül kell definiálnunk. -
GetHashCode()/hashCode(): Egy egyedi számot (hash kódot) állít elő az objektumból, ami gyorsítja a keresést a gyűjteményekben. Szabály: Ha két objektum azEqualsszerint egyenlő, akkor a hash kódjuknak is kötelezően egyenlőnek kell lennie.
2. Értéktípusok és a Boxing (Bedobozolás)
A C#-ban az egyszerű típusok (mint az int, double stb.) értéktípusok. Létezik azonban egy mechanizmus, amellyel ezeket referenciatípusként (objektumként) is tudjuk kezelni.
-
Boxing (Bedobozolás): Amikor egy értéktípusból egy
object(referencia) típust hozunk létre (pl.object obj = 10;). Ilyenkor a memóriában lefoglalódik egy objektum, és az érték bemásolódik oda. -
Unboxing (Kidobozolás): Amikor a bedobozolt objektumból visszanyerjük az eredeti értéktípust egy explicit konverzióval (pl.
int x = (int)obj;).
A memóriakímélés érdekében a C# biztosítja a Struktúrákat (struct). Ezek olyanok, mint az osztályok, de az Object helyett a System.ValueType osztályból származnak, azaz értéktípusként viselkednek. Értékadáskor (=) egy struktúráról mindig egy teljesen új, független másolat készül a memóriában, nem pedig egy új referencia mutató. A struktúrák automatikusan véglegesek (sealed), nem lehet belőlük örökölni.
3. Szövegkezelés (String és StringBuilder)
A String típus (C#-ban string) egy karakterekből álló sorozat.
A legfontosabb tulajdonsága mindkét nyelvben, hogy megváltoztathatatlan (immutable). Ez azt jelenti, hogy ha egy már létező stringhez hozzáadunk egy új szót, akkor a memóriában nem a régi objektum bővül ki, hanem létrehoz a gép egy teljesen új string objektumot a memóriában. Ciklusban történő, többszöri szöveg-összefűzés esetén ez nagyon lelassítja a programot.
A string osztály fontosabb metódusai a C#-ban: .Split(), .Replace(), .Substring(), .Contains().
Ha sokszor akarunk módosítani egy szöveget, akkor a StringBuilder osztályt kell használni. Ez nem hoz létre minden módosításnál új objektumot, hanem egy allokált memóriaterületen belül módosítja magát a szöveget, így sokkal gyorsabb. Metódusai például az .Append() (hozzáfűzés) és a .Clear().
4. Dátum és Idő kezelése (C#)
A C#-ban a pontos idő és dátum kezelésére a System.DateTime struktúra szolgál.
-
Aktuális időpont lekérése:
DateTime.Now. -
Példányosítás megadott adatokkal:
new DateTime(2020, 4, 20). -
Egyes összetevők (év, hónap, nap) kiolvasására a
.Year,.Month,.Daytulajdonságok szolgálnak.
Ha két DateTime objektumot kivonunk egymásból, az eredmény nem egy dátum lesz, hanem egy időintervallum, amit a System.TimeSpan struktúra tárol.
-
A
TimeSpansegítségével lekérdezhetjük, hány nap, óra vagy másodperc telt el a két időpont között (pl..TotalDays). -
Dátumokhoz egyszerűen adhatunk is hozzá időt az
.AddDays(),.AddHours()metódusok segítségével.
Gyakorló feladat
Készíts egy programot, amely bemutatja az Object osztály metódusainak felüldefiniálását és a dátumok kezelését!
-
Hozz létre egy
Szerzodesnevű osztályt! Legyen két tulajdonsága:UgyfelNev(string) ésLejarat(DateTime). -
Írj egy paraméteres konstruktort, amely beállítja ezeket.
-
Definiáld felül (override) a
ToString()metódust úgy, hogy egy szép formátumban kiírja az ügyfél nevét és a szerződés lejáratának dátumát. -
Írj egy metódust
HatranyosNapok()néven aSzerzodesosztályon belül! Ez a metódus aDateTime.Nowés a lejárat dátumának különbségéből (TimeSpan) számolja ki, hogy hány nap van még hátra a lejáratig. -
A
Mainmetódusban hozz létre egy szerződést egy jövőbeli dátummal, írasd ki az adatait (ami a saját ToString-edet fogja meghívni), majd írasd ki a hátralévő napok számát is!
A feladat megoldása
using System;
class Szerzodes
{
public string UgyfelNev { get; set; }
public DateTime Lejarat { get; set; }
public Szerzodes(string nev, DateTime lejarat)
{
this.UgyfelNev = nev;
this.Lejarat = lejarat;
}
// 3. ToString() felüldefiniálása
public override string ToString()
{
return $"Szerződés: {this.UgyfelNev}, Lejárat: {this.Lejarat.ToShortDateString()}";
}
// 4. Hátralévő napok kiszámítása TimeSpan segítségével
public int HatranyosNapok()
{
DateTime ma = DateTime.Now;
TimeSpan kulonbseg = this.Lejarat - ma;
// A TotalDays egy tört szám, ezért (int)-re castoljuk
return (int)kulonbseg.TotalDays;
}
}
class Program
{
static void Main(string[] args)
{
// 5. Tesztelés jövőbeli dátummal
DateTime jovohet = DateTime.Now.AddDays(10);
Szerzodes sz1 = new Szerzodes("Nagy Kft.", jovohet);
// Ez a háttérben meghívja a felülírt ToString() metódust!
Console.WriteLine(sz1);
Console.WriteLine($"A szerződés lejáratáig még {sz1.HatranyosNapok()} nap van hátra.");
Console.ReadKey();
}
}