270 likes | 392 Views
Microsoft.NET környezet. Hernyák Zoltán Programozási Nyelvek II. Eszterházy Károly Főiskola Számítástudományi tsz. 1. Típuskompatibilitás. Ha egy ‘A’ típus kompatibilis egy ‘B’ típussal, akkor minden olyan helyen, ahol egy ‘B’ típusú kifejezés
E N D
Microsoft.NET környezet Hernyák Zoltán Programozási Nyelvek II. Eszterházy Károly Főiskola Számítástudományi tsz 1
Típuskompatibilitás Ha egy ‘A’ típus kompatibilis egy ‘B’ típussal, akkor minden olyan helyen, ahol egy ‘B’ típusú kifejezés (változó) szerepelhet, ott szerepelhet egy ‘A’ típusú kifejezés (változó) is. Pl: az ‘int’ kompatibilis típus a ‘double’-val, ezért: void Kiszamol(double x) { ... } … az alábbi módokon meghívható: double a = 10; Kiszamol( a ); int b = 10; Kiszamol( b ); 2
Típuskompatibilitás Az OOP-ben egy ‘B’ objektumosztály kompatibilis egy ‘A’ objektumosztállyal, ha az ‘B’-nak az ‘A’ őse. Ez egy tranzitív tulajdonság! A class A_oszt { ... } class B_oszt:A_oszt { ... } E B C D 3
Típuskompatibilitás Az OOP-ben egy ‘B’ objektumosztály kompatibilis egy ‘A’ objektumosztállyal, ha az ‘B’-nak az ‘A’ őse. A fenti egyébként természetes, hiszen ekkor B-nek minden mezője és metódusa meg lesz, ami az A-ban definiált (öröklődés). Ezért természetes, hogy minden olyan helyen, ahol egy A példány használható, ott egy B példány is. 4
Típuskompatibilitás class TElso { ... } class TMasodik { ... } class MainClass { static void Kiir(TElso x) { Console.WriteLine(x); } static void Main() { TElso e = new TElso(); TMasodik m = new TMasodik(); Kiir(e); // ??? Kiir(m); // ??? } } 5
Típuskompatibilitás class TElso { public int szam=10; ... } class TMasodik:TElso { ... } class MainClass { static void Kiir(TElso x) { Console.WriteLine(x.szam); } static void Main() { TElso e = new TElso(); TMasodik m = new TMasodik(); Kiir(e); // ??? Kiir(m); // ??? } } 6
Típuskompatibilitás class TElso { public int szam=10; ... } class TMasodik:TElso { ... } class MainClass { static void Kiir(TElso x) { Console.WriteLine(x.szam); } static void Main() { TElso e = new TElso(); TMasodik m = new TMasodik(); Kiir(e); // ??? Kiir(m); // ??? } } 7
Típuskompatibilitás TElso e; e = new TElso(); Két lépéses példányosítás… TMasodik m = new TMasodik(); e = m; Típuskompatibilitás ! e = new TMasodik(); TElso e = new TMasodik(); Ekkor melyik VMT lesz az ‘e’ pédányhoz hozzárendelve? TMasodik m = new TElso(); Ez típushelyes értékadás? 8
Típuskompatibilitás A VMT-t a konstruktor rendeli a példányhoz. Ezért hogy melyik VMT kerül a példányhoz hozzárendelésre, azt az a konstruktor dönti el, amelyik a példányosítás során meghívásra kerül, és nem az azonosító típusa. 9
Típuskompatibilitás class TElso { public int szam() { return 10; } ... } class TMasodik:TElso { ... } class MainClass { static void Kiir(TElso x) { Console.WriteLine(x.szam()); } static void Main() { TElso e = new TElso(); TMasodik m = new TMasodik(); Kiir(e); // mit fog kiirni ? Kiir(m); // ??? } } 10
Típuskompatibilitás class TElso { public int szam() { return 10; } ... } class TMasodik:TElso { new public int szam() { return 20; } ... } public void Kiir(TElso x) { Console.WriteLine(x.szam()); } TElso e = new TElso(); TMasodik m = new TMasodik(); Kiir(e); // mit fog kiirni ? Kiir(m); // ??? Korai kötés ! 11
Típuskompatibilitás class TElso { public virtual int szam() { return 10; } ... } class TMasodik:TElso { public override int szam() { return 20; } ... } public void Kiir(TElso x) { Console.WriteLine(x.szam()); } TElso e = new TElso(); TMasodik m = new TMasodik(); Kiir(e); // mit fog kiirni ? Kiir(m); // ??? Késői kötés ! 12
Típuskompatibilitás class TElso { public virtual int szam() { return 10; } ... } class TMasodik:TElso { public override int szam() { return 20; } ... } public void Kiir(TElso x) { Console.WriteLine(x.szam()); } TElso e = new TElso(); TElso m = new TMasodik(); Kiir(e); // mit fog kiirni ? Kiir(m); // mi a VMT ? Késői kötés ! 13
Típuskompatibilitás class TElso { public int szam =0; public TElso() { szam = 10; } ... } class TMasodik:TElso { public TMasodik() { szam = 20; } ... } public void Kiir(TElso x) { Console.WriteLine( x.szam ); } TElso e = new TElso(); TElso m = new TMasodik(); TMasodik x = new TMasodik(); 14
Típuskompatibilitás class TElso { public int szam =0; public TElso() { szam = 10; } ... } class TMasodik:TElso { new int szam = 0; public TMasodik() { szam = 20; } ... } public void Kiir(TElso x) { Console.WriteLine( x.szam ); } TElso e = new TElso(); TElso m = new TMasodik(); TMasodik x = new TMasodik(); 15
Típusellenőrzés public void Kiir(TElso x) { if (x is TElso) ...; if (x is TMasodik) ...; } A típusellenőrzés az ‘is’ operátorral történik. Alakja: <PÉLDÁNY> is <OSZTÁLY> Az ‘is’ logikai igaz (true) vagy hamis (false) értéket ad meg. Logikai igaz, ha a megadott példány kompatibilis típus a megadott osztállyal. 16
Típusellenőrzés public void Kiir(TElso x) { if (x is TElso) ...; if (x is TMasodik) ...; } Ebben a példában az (x is TElso) biztosan igaz értéket ad meg, hiszen ezt már a fordítóprogram leellenőrízte, hogy ezt a metódust TElso kompatibilis példánnyal hívják-e meg (formális és aktuális paraméterlista- ellenőrzés közben). Az (x is TMasodik) igaz értéket ad meg, ha az aktuális paraméterlistában TMasodik, vagy belőle származta- tott típusú példány szerepelt. 17
Típusellenőrzés public void Kiir(TElso x) { if (x is TElso) (x as TElso).Kiir(); if (x is TMasodik) (x as TMasodik).Feltolt(); } A típuskényszerítés az ‘as’ operátorral történik. Alakja: <PÉLDÁNY> as <OSZTÁLY> A kifejezés ezen részén az adott azonosító úgy viselkedik, mintha a megadott osztályú lenne ( ekkor működik az adott osztályra a korai kötés is ). A késői kötés működéséhez ez a típus- kényszerítés nem szükséges – az e nélkül is működik. 18
Típusellenőrzés A típuskényszerítés történhet a C-s formában is Alakja: (OSZTÁLY)PÉLDÁNY public void Kiir(TElso x) { if (x is TElso) ((TElso)x).Kiir(); if (x is TMasodik) ((TMasodik)x).Feltolt(); } Sajnos a ‘.’ (pont) operátor magasabb prioritású, mint a típuskényszerítés, ezért az alábbi forma nem megfelelő: (TMasodik)x.Feltolt(); Ez szintaktikailag nem helytelen, de jelentése szerint a Feltolt() által visszaadott értéket típuskényszeríti ‘TMasodik’ típusra… 19
Típuskompatibilitás class TElso { public int szam = 10; ... } class TMasodik:TElso { public new int szam = 0; ... } public void Kiir(TElso x) { if (x is TMasodik) Console.WriteLine( (x as TMasodik).szam ); else Console.WriteLine( x.szam ); } 20
Típuskompatibilitás class TElso { public int szam() { return 10; } ... } class TMasodik:TElso { new public int szam() return 20; } ... } public void Kiir(TElso x) { if (x is TMasodik) Console.WriteLine( (x as TMasodik).szam() ); else Console.WriteLine( x.szam() ); } 21
Típusellenőrzés Ha a típuskényszerítés nem végrehajtható, mert a példány mégsem kompatibilis a megadott típussal, akkor futási hiba keletkezik (InvalidCastException). Ezért típuskényszerítés ( ‘as’ ) mindig ellenőrizzük le, hogy a kompatibilitás fennáll-e az ‘is’ operátorral!!!! 22
Típuskompatibilitás C#-ban ha egy osztálynak nincs megjelölt őse, akkor a nyelv automatikusan az Object osztályt rendeli hozzá ősnek! Object class A_oszt { ... } D A B C class A_osztaly:Object { ... } 23
Típuskompatibilitás E miatt minden példány mindig kompatibilis az Object típussal ! if (x is Object) ... if (x is Object) (x as Object)... public static void Akarmi(Object x) { ... } Tetszőleges osztály tetszőleges példánya átadható paraméterként, hiszen biztosan kompatibilis lesz az Object típussal… 24
Típuskompatibilitás class ArrayList { public void Add(Object item) { ... } class Stack { public void Push(Object item) { ... } public Object Pop() { ... } class Console { public static void WriteLine(Object item) { ... } 25
Típuskompatibilitás Stack st = new Stack(); ... TSajat t = new TSajat(); st.Push( t ); // működik ... TSajat x = st.Pop(); // nem működik ! TSajat x = st.Pop() as TSajat; // nem biztoságos TObject o = st.Pop(); if (o is TElso) t = o as TElso; // biztonságos 26
Típuskompatibilitás class TElso { public int eletkor = 10; } Class TMasik:TElso { public double suly = 20.4; } static void Beallit(TElso x) { x.eletkor = 11; x.suly = 23.4; if (x is TMasik) x.suly = 23.4; (x as TMasik).suly = 23.4; if (x is TMasik) (x as TMasik).suly = 23.4; } TElso e = new TElso(); Beallit( e ); TMasik m = new TMasik(); Beallit( m ); TElso f = new TMasik(); Beallit( f ); Mikor mi fog történni? 27