Mivel jobb ha Én magam hozok létre konstruktort és nem az üreset használom?(OOP)(C#)
Emelt ágazati érettségire készülök és egy régebbi feladatot próbálok átírni
Objektum orientáltra, hogy megpróbáljam felfogni. Az lenne a kérdésem, hogy tényleg sok leírást olvastam róla, de egyszerűen nem tudom megérteni, vagy csak elfut a szemem előtt, hogy mégis mivel jobb a saját konstruktorom?
Saját Konstruktorral:
class Futar
{
public int napokSorszama;
public int Fuvarszam;
public int Megtettut;
public Futar(int napok, int szam, int ut)
{
this.napokSorszama = napok;
this.Fuvarszam = szam;
this.Megtettut = ut;
}
}
.
.
.
static List<Futar> FutarSzolgalat = new List<Futar>();
.
.
Beolvasás
.
.
.
string[] toredek = szoveg.Split(' ');
FutarSzolgalat.Add(new Futar(int.Parse(toredek[0]), int.Parse(toredek[1]), int.Parse(toredek[2])));
Az alap üres konstruktorral:
Adatok adat = new Adatok();
Beolvasás
.
.
.
string[] toredek = szoveg.Split(' ');
adat.NapokSorszama = Convert.ToInt32(toredek[0]);
adat.Fuvarszam = Convert.ToInt32(toredek[1]);
adat.MegtettUt = Convert.ToInt32(toredek[2]);
Futar.Add(adat);
Néhány érv az első mellett a teljesség igénye nélkül:
- ha több példányt hozol létre, akkor nem kell mindegyiknél egyesével felsorolni az adattagok feltöltését, nincs ismétlés, egyszerűbb később kezelni a kódot
- vannak esetek, amikor az adattagok privát vagy protected láthatóságúak; ilyen esetekben a konstruktoron, vagy valamilyen setteren keresztül állítjuk be ezeket az értékeket
- a második megoldásnál nem enkapszulálod a kezdeti adatok megadását, azaz van egy olyan állapota a hívó kódnak, amikor csak félig van inicializálva az osztályod; az ilyen eseteket mindenhol érdemes kerülni
- a logika sem elhanyagolható szempont: ha valaminek van kezdeti értéke, akkor azt nem a létrehozás után állítjuk be egy módosítással, hanem alapból úgy hozzuk létre
Valószínűleg egyrészről a tanárok hibája, amiért nem tudják megfelelően átadni az OOP szemléletet, de sokan egyszerűen csak több év gyakorlás után értik meg bizonyos dolgok értelmét (jómagamon is tapasztaltam).
Az OOP alapelvei között szerepel az Egységbezárás címszó:
Azt jelenti, hogy az adatstruktúrákat és az adott struktúrájú adatokat kezelő függvényeket (metódusokat) kombináljuk. Azokat egy egységként kezeljük, és ELZÁRJUK ŐKET A KÜLVILÁG ELŐL. Az így kapott egységeket objektumoknak nevezzük.
Tehát, bezárod az adattagjaidat az osztályba, hogy senki más ne nyúlhasson hozzá kívülről. Azért jó, mert így 100%-ig biztosíthatod, hogy csak az osztályon belül romolhat el valami, ha nem az elvárt módon viselkedik az osztályod tesztelés során. Másrészről tuti biztos, hogy senki nem fogja kívülről megváltoztatni az osztály működését, így nem kell csomó esetre lekezelned az osztály függvényeit. Hogyan viselkedjen, ha Fuvarszam adataggod nem létezik vagy inkonzisztens, hogyan vislekedjen, ha a napokSorszama a függvény közepén valamiért megváltozott egy asynchron hívás miatt, stb.
Sokat kell még gyakorolnod, hogy a fenti lényegét megértsd, de röviden, sokkal biztonságosabb és stabilabb a kódod, ha a konstruktorban inicializálsz és nem az osztály más pontján. Főleg nem kívülről. Ilyet: "adat.Fuvarszam = Convert.ToInt32(toredek[1]);" nagyon ritkán csinálunk, és leggyakrabban csak Data Model/Entity osztályokon.
A konstruktornak 3 feladata van:
1) Lefoglalja a memóriát az objektum számára.
2) Kezdőállapotba hozza az objektumot. (Állapot = az objektum tulajdonságai milyen értékekkel rendelkeznek; Kezdőállapot = az objektum tulajdonságainak értéke közvetlenül a konstruktor lefutása után)
3) Visszaadja a referenciát/pointert az objektumra.
A programozási nyelvek az első és az utolsó lépést szépen elrejtik előled. A te feladatod a második lépés megírása.
Normális esetben a konstruktorban kérsz be minden olyan adatot, amik hiánya esetén az objektumod nem tud működni. Néhány példa erre:
- Tegyük fel, hogy valamilyen üzleti logikát megvalósító osztályt írsz, és az adott üzleti művelet elvégzéséhez szükséged van adatbázis-kapcsolatra.
- Tegyük fel, hogy az osztályod valamilyen entitást (élőlény, tárgy, jelenség vagy fogalom) reprezentál. Mondjuk egy számlát. De az üzlet szerint nem létezhet olyan számla, amelynek nincs egy kiállítója, nincs vásárló, nincs sorszáma stb.
Hogy kikényszerítsd ezeket a követelményeket, paraméterezett konstruktort használhatsz. Ezáltal létre sem lehet olyan objektumokat létrehozni, amiben ezek a kötelező függőségek nincsenek megadva.
Van még egy eset: az immutable objektumok.
Vannak olyan esetek, amikor paraméter nélküli konstruktort használsz:
- Nincs semmilyen kötelezően megadandó függősége az adott osztálynak (legyen szó adatról vagy más szolgáltatásról). Ha van neki valamilyen függősége mégis, azok opcionálisak.
- A Builder design patternt alkalmazod.
- Egy általad használt valamilyen framework alkalmazza az ún. constrained constructor antipatternt, vagyis szigorúan csak olyan osztályokkal tud együttműködni, amelynek a konstruktora valamilyen speciális szignatúrával rendelkezik. Ilyen például a legtöbb UI framework (WinForms és WPF), a szerializálás, egyes MVC frameworkök, stb. A legtöbb framework, amely ezt az antipatternt alkalmazza, pont azt várják el, hogy az osztályodnak ne legyen konstruktora. Többek között ezért is nem fogsz tudni Dependency Injection Containert használni például egy WPF alkalmazásban, csak a Service Locator antipatternt.
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!