C# ben hogyan lehetséges az, hogy ha egy object típushoz ha hozzárendelek egy származtatottat akkor az object ből visszafejthető származtatott típusá?
Például.
object o = new Animal();
Animal a = (Animal)o;
Ez,azért lehetséges mert az object az alapból kontravariáns?
Az érthető számomra,hogy egy származtatott típus castolódik bázis típusra de egy bázis típusból mégis,hogyan lehet kinyerni egy származtatott típust ha egyszer nem tartalmazza azt?
Pár fontos fogalmat kell itt tisztázni. A helyettesíthetőség, a statikus és a dinamikus típus.
A helyettesíthetőség azt jelenti, hogy egy leszármazott osztály példánya a program szövegében minden olyan helyen megjelenhet, ahol az előd osztály példánya. Vagyis, legyen A egy osztály és B az A leszármazott osztálya. Ekkor ahová én az A-nak a példányát írhatom, írhatom a B-nek a példányát.
Pár példa:
A valami = new B();
public static void Valami(A obj) { }
Valami(new B());
Az OOP paradigma szerint minden osztály, az Object-et kivéve, az Object osztály leszármazottja. Ezért írhatod azt, hogy:
object o = new Animal();
A statikus típus azt jelenti, hogy milyen típusú változóba példányosítod az osztályt.
Például az
object o = new Animal();
kódban a statikus típus az object lesz. Ez fix, és nem tudod megváltoztatni. Ezért statikus típus.
Itt a helyettesíthetőség szintén fontos szerepet játszik, hiszen csak az osztály vagy előd osztály típusú változóba példányosíthatok bele. Vagyis én ilyet nem írhatok le:
class Kutya {}
class Macska {}
Macska a = new Kutya();
Viszont ez menni fog:
class Kutya {}
class Spaniel : Kutya {}
Kutya bodri = new Spaniel();
De ez nem fog menni a helyettesíthetőség szabálya miatt: Spaniel a = new Kutya();
A dinamikus típus azt jelenti, hogy a statikus típusú változó milyen típusú értéket tárol.
object o = new Animal();
Ebben az esetben a dinamikus típus az Animal lesz. Azért dinamikus típus, mert a helyettesíthetőség szabálya szerint én ezt behelyettesíthetem minden olyan helyre, ahol ennek az osztálynak vagy valamelyik előd osztály példányának kellene szerepelnie.
public static void Valami(Animal a) {}
public static void Valami2(object a) {}
Animal o = new Animal();
Valami(o);
Valami2(o);
Viszont, ha én statikus típusnak valamelyik előd osztályt adtam meg, megpróbálhatom típuskényszeríteni valamelyik leszármazott osztályba, amennyiben a dinamikus típus megfelel ennek. Például:
object o = new Animal();
Animal a = (Animal)o;
Az egyes objektumok a memóriában nem igazán különböznek egymástól: az adattagjaik vannak valahogy letárolva. A típusuk mondja meg, hogy ezekkel az adattagokkal milyen műveleteket lehet végezni.
A példádban a második sor, csak akkor fog lefutni helyesen, ha az o valóban Animal (vagy annak egy származtatott típusa). Ha pl String lenne, akkor futás időben hibát kapnál.
Ahhoz hogy ilyenbe ne szaladj bele érdemes futás ellenőrizni a típust castolás előtt.
"Példádban a második sor, csak akkor fog lefutni helyesen, ha az o valóban Animal"
De miért működik hisz egy bázis típus nem tartalmazhatja a leszármazott részt.Mert az object az object ez pedig azért van így mert az objectnek nincs őse.
De az animal egyben egy object is.
Miért működik ez mégis akkor:
Animal a = (Animal)o;
Sosem szabadna jó lenni ennek az explicit konverziónak mert egy bázis típus sosem lehet származtatott típus is.
Az egész Neumannal kezdődött :D
A memóriában együtt tárolódik a program, és az adat
Ha ráböksz egy memóriarekeszre, a büdös életben nem mondod meg, hogy az adat, program, vagy szemét
Valahogy pont ugyanígy megy az egész itt is
Attól, hogy az o változód Object, attól az még csak egy mezei pointer, attól a cím az cím, attól te még az általa mutatott objektumra rámondhatod, hogy ez egy animál, oszt' akkor állatként értelmezed, és kész
előbb az oop alapokkal kéne tisztában lenni, nem?
Tisztában vagyok vele éppen ezért kérdezem.
Egy származtatott típus azért rendelhető hozzá a bázis típusához mert a származtatott egyben egy bázis típus is.
De ha bázis típus akarunk származtatotthoz rendelni,akkor ez már nem érthető mert a bázis típus soha és egy kicsit sem rendelkezik a leszármazott osztály típusával.
De mégis működik ezt nem értem,hogy miért.
"object típushoz ha hozzárendelek egy származtatottat akkor az object ből visszafejthető származtatott típussá"
valószínűleg te azt gondolod, hogy mikor hozzárendeled az objecthez, akkor történik valamiféle "ollózás", ami lecsupaszítja a származtatottat objectté
de semmi ilyen nem történik, mert ez nem így működik, erről beszéltem az előbb, hogy az o csak egy pointer, semmi más
Nem értem.
Hogyan lehetséges az object ből animalt csinálni ha az objectbe csak az Animal osztály object része van benne.
Csak is az lehet benne mert le kasztolódott az animal objectre.
Felfogtátok már. :(
Nem igaz hogy nem értitek pedig jól magyarázok.
Az előző hozzászólásomat akkor írtam ki amikor még nem láttam az utolsó válaszoló hozzászólását.
Ezért az előző hozzászólásomat vegyétek semmisnek.
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!