Programozsi Paradigmk s Technikk Programozsi eszkzk Interfszek Generikus
- Slides: 43
Programozási Paradigmák és Technikák Programozási eszközök Interfészek Generikus osztályok Operator overloading Adatstruktúrák Láncolt Lista Bináris fa Gráfok Dijkstra algoritmus Kruskal algoritmus V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 1
Programozási Paradigmák és Technikák Programozási eszközök Interfészek Generikus osztályok Operator overloading Adatstruktúrák Láncolt Lista Bináris fa Gráfok Dijkstra algoritmus Kruskal algoritmus V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 2
Interfészek • Metódusok "előírására", kötelezővé tételére használható • Az osztályban kötelezően kell lennie egy publikus Eldönt() eljárásnak (ha nincs: a fordító reklamál) • Hasonló, de teljesen másra használt : absztrakt osztály • Kifejezés: "az X osztály, struktúra implementálja az Y interfészt" V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 3
Interfészek - lehetőségek • Egy interfészt implementáló osztály példányosítható egy interfész típusú változóba: IEldönthető valtozo=new Saját. Osztály(); • Egy interfész-metódus elérhető az osztálypéldányon keresztül: Saját. Osztály valtozo=new Saját. Osztály(); valtozo. Eldönt(); • … Vagy az interfészen keresztül: (valtozo as IEldönthető). Eldönt(); • Ez utóbbira akkor van szükség, ha explicit megvalósítású az interfész az osztályban, vagy a változó típusából nem egyértelmű az interfész implementálása V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 4
Explicit implementáció • Azonos eljárást előíró interfészek esetén lehet szükséges V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 5
Explicit Implementáció V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 6
Explicit implementáció használata • A következő órán fogunk saját interfészt létrehozni, ezen az órán csak meglévő interfészeket használunk V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 7
Interfészek használata • Tipikusan: funkcionalitás előírásánál, avagy előírásnak megfelelésnél (pl. VEP: ha az INotify. Property. Changed interfészt implementálom egy olyan osztálynál, aminek a példányait List. Box vezérlőben helyezem el, akkor ez előír egy eseményt, amire a List. Box feliratkozik – ezen az eseményen keresztül tudja a List. Box, ha frissítenie kell) • "A változó típusából nem egyértelmű az interfész implementálása" Ugyanaz, mint amikor OOP-ben ős típusú volt a tömb, és nem tudtuk, hogy az egyes tömbelemek milyen típusúak • Van olyan eset, amikor a gyűjteményből/tömbből csak néhány elem implementál egy bizonyos interfészt, az interfész implementálását ugyanúgy az IS kulcsszóval lehet ellenőrizni V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 8
Interfészek használata V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 9
Interfészek használata • Array. Sort(tömb) tömb rendezése. int[] esetén tökéletesen működik • Készítsünk egy osztályt, amelynek segítségével hallgatókat tudunk tárolni: név, neptun kód, teljesített kreditek • Töltsünk fel egy 10 elemű tömböt hallgatókkal. Hogyan tudjuk ezt a tömböt a fenti módon névsorba vagy teljesített kreditek szerinti sorba rendezni? IComparable. Compare. To(object) V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 10
Programozási Paradigmák és Technikák Programozási eszközök Interfészek Generikus osztályok (© Erdélyi Krisztina) Operator overloading Adatstruktúrák Láncolt Lista Bináris fa Gráfok Dijkstra algoritmus Kruskal algoritmus V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 11
Generikus Osztályok • • V 1. 0 A generic fogalma Generikus osztályok Generikus metódusok Megszorítások Statikus tagok Öröklés A generic-ek működése. NET-ben Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 12
Bevezetés Klubok (angol-társalgás, kirándulás) tevékenységét segítő szoftvert szeretnénk készíteni. Fontos, hogy egy személy egyetlen egyszerepeljen egy klubban, hiszen különben a két „példánya” önálló életet élne. Hogyan célszerű ezt megvalósítani? Próbáljuk minél általánosabban megoldani a feladatot! Lehet, hogy jövőre kutya-klubos szoftvert kell készítenünk. V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 13
Bevezetés – megoldási javaslatok • Célszerű halmaz típust létrehozni, mert az egy elemet egyszer tartalmazhat • Milyen elemekből álljon a halmaz? – Személy – akkor a kutya-klubhoz át kell írni – A személy és a kutya őse – ez biztos, hogy elég általános? – Object ez mindennek az őse - ez lehet megoldás Array. List, . NET 1, csak object-et tárol, állandó castolás – A típust adjuk meg paraméterként , így elég a deklarációban megadni a konkrét típust – ez is megoldás Vizsgáljuk meg ezt közelebbről! V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 14
A generic fogalma. NET-ben • Paraméterezett típus vagy metódus • Mindenegyes paraméter egy még meg nem határozott típus helye • Más néven sablon vagy template • Az osztály deklarációjakor csak T néven hivatkozok a típusra, csak az osztály példányosításakor definiálom, hogy ez a T pontosan mi V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 15
Paraméterezett típusok • A paraméter a típus fejrészében helyezkedik el class My. Generic. Class <T> { } • Deklarációnál és példányosításkor az aktuális típus kerül a paraméter helyére My. Generic. Class < int> mg c. INT = new My. Generic. Class < int>(); • A generic-ek tipikusan gyűjtemények létrehozásához valók, mivel a gyűjtemények több típussal is használhatók V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 16
Generikus gyűjtemények • Array. List object típust tárol, állandó castolás, elavult • List<T>: Add(), Insert(), Remove. At(), Reverse(), [], Clear(), Contains(), Count • Queue<T>: Enqueue(), Dequeue(), Peek(), Clear(), Contains(), Count • Stack<T>: Push(), Pop(), Peek(), Clear(), Contains(), Count • Dictionary<T, U>: Add(), Remove(), Try. Get. Value(), Keys, Values, Clear(), Contains. Key(), Contains. Value(), Count V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 17
Saját generikus osztály létrehozása V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 18
Generikus osztály használata V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 19
Paraméterezett típus inicializálása • Nem tudható, hogy érték vagy referencia típusú-e a paraméter • Megoldás: default expression – Referenciánál null-t ad vissza – Érték típusnál bitenkénti nullát V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu this. elem = default(T); 20
Megszorítások • Lefordulnak a következő kódok? • Ha nem, akkor mi a megoldás? • Annyit feltételezhetünk, hogy a T típus a System. Object-ből származik • Ezért ennek megfelelően viselkedik V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 21
Interfész megszorítás class My. Class 2<T> { public void Iterate(T data) { foreach (object item in data) { Console. Write. Line(item); } } Nem biztos, hogy T felsorolható! } (A foreach ciklus akkor működik saját típuson, ha a saját típus megvalósítja a IEnumerable<T> interfészt, ld. később) class My. Class 2<T> where T : IEnumerable<T>{ public void Iterate(T data) { foreach (object item in data) { Console. Write. Line(item); } } } OK V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 22
Konstruktor megszorítás class My. Class<T> { T obj = new T(); } Nem biztos, hogy T-nek van alapértelmezett konstruktora! class My. Class<T> where T: new() { T obj = new T(); } OK V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 23
Művelet megszorítás? ? ? class Arithmetic<T>{ Nem biztos, hogy T-n public T Cubed(T number){ return number * number; értelmezett a szorzás! } } class Arithmetic<T> where T : System. Int 32{ public T Cubed(T number){ return number * number; } Érték és primitív } típusok nem lehetnek megszorítások! Súlyos korlátja a generic-ek használatának, hogy standard operátorok az érték típusokkal nem használhatók. V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 24
A Generic korlátja class Program 2 { A standard operátorok public T Min<T>(T a, T b) nem használhatók. where T : IComparable<T> { if (a<b) return a; class Program else { return b; public T Min<T>(T a, T b) } where T : IComparable<T> } { if (a. Compare. To(b)<0) return a; else return b; }… Szabó Zsolt, Óbudai Egyetem, 2011 V 1. 0 25 } szabo. zsolt@nik. uni-obuda. hu
Megszorítások • A megszorítások a típus paraméterektől elvárt viselkedést írják le • A where kulcsszóval vezetjük be • Típusnál és metódusnál is használhatók • Fajtáik: – – – Leszármazott ( where T : Személy ) Interfész ( where T: IEnumerable <T> ) Érték típus ( where T: struct) Referencia típus ( where T: class) Konstruktor ( where T: new()) • Az alábbi típusok nem lehetnek megszorításban: V 1. 0 – – – Lezárt osztályok Primitív típusok System. Array System. Delegate System. Enum Szabó Zsolt, Óbudai Egyetem, 2011 System. Value. Type szabo. zsolt@nik. uni-obuda. hu 26
Generikus metódus • • V 1. 0 Tartozhat generikus vagy nem generikus típushoz Attól mert, a típus generikus, a metódus még nem A metódus generikus, ha saját típusparamétere(i) van(nak) A típusparaméter megjelenhet visszatérési értékként vagy a paraméterlistában Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 27
Generikus metódusok meghívása • A metódus meghívásakor a paraméterek típusa adja meg a típusparaméter aktuális értékét: int i=Min(2, 3); //egészek float f=Min(2. 0, 3. 0); //valósak • Ellentmondás esetén a nem-generikus eljárás hívódik: mi van, ha T=int? a nem-generikus változat hívódik meg • Ha két generikus metódus van különböző generikus paraméterrel pl. Method(T arg), Method(U arg), és T és U konkrétan ugyanaz, akkor a metódus meghívásánál jelez hibát. V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 28
Statikus tagok • A statikus tagok eléréséhez be kell helyettesíteni egy konkrét típust a paraméterbe My. Generic. Class < int>. Count(); • Különböző behelyettesített típusokhoz különböző statikus tagok tartoznak • A statikus konstruktor implicit meghívódik, és a behelyettesített típusnak megfelelően inicializálja a statikus mezőket V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 29
Példányok számolása class My. Generic. Class<T> { private static int counter = 0; public My. Generic. Class() { counter++; } public static void Count() { Console. Write. Line(counter); } } V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 30
Generikus osztályok az öröklésben • Generikus osztály lehet őse generikus és nem generikus osztálynak • Generikus osztály származhat generikus vagy nem generikus osztályból • De mindkét állítás csak bizonyos esetekben igaz! • Gondoljunk arra, hogy az utód példányosításakor a típusparaméterek értékét mindenképpen meg kell határozni V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 31
Generikus osztályok az öröklésben Melyik eset lehetséges? V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 32
Generikus osztályok az öröklésbenés a. NET-ben • A típusra vonatkozó ős osztálybeli megszorításokat az utódosztályban meg kell ismételni • Az utódosztály tartalmazhat további megszorításokat • Nem nyelvspecifikus, minden felügyelt nyelvben elérhető • A köztes kódra való fordítás során metaadatok és a generic-ekre vonatkozó MSIL kód áll elő • A JIT fordítás során történik meg a konkrét típusok behelyettesítése • Lehetőség van több típus használatára: class valami<T, U> { } V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 33
A generic-ek működése. NET-ben A fenti kódhoz három osztály jön létre. A két My. Generic. Class<int> osztozik egy osztályon. A My. Generic. Class<double> külön osztály. A My. Generic. Class<Személy> és a My. Generic. Class<Pizza> osztozik egy osztályon. V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 34
Feladat: halmaz • Hozzunk létre egy generikus halmaz<T> osztályt, amelyben List<T> segítségével tároljuk az elemeket • Kell: konstruktor, copy konstruktor, elem hozzáadása • Cél: foreach ciklus működjön: V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 35
IEnumerable / IEnumerator • A foreach ciklus akkor működik saját típuson, ha a saját típus megvalósítja a IEnumerable<T> interfészt • Ez az interfész előírja a Get. Enumerator() eljárást, ami visszaad egy olyan objektumpéldányt, ami megvalósítja az IEnumerator<T> interfészt • Az IEnumerator<T> előírja a következő műveleteket: Aktuális elem olvasása (Current), következő elemre mozgás (Move. Next()), visszaállás az első előtti elemre (Reset()) lista bejárása • Mindegyik interfész előírja a nemgenerikus ( object) változatot is • Saját enumeratort a következő órán fogunk implementálni, addig meglévő enumeratort használunk Szabó Zsolt, Óbudai Egyetem, 2011 V 1. 0 szabo. zsolt@nik. uni-obuda. hu 36
Programozási Paradigmák és Technikák Programozási eszközök Interfészek Generikus osztályok Operator overloading Adatstruktúrák Láncolt Lista Bináris fa Gráfok Dijkstra algoritmus Kruskal algoritmus V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 37
Operator Overloading • halmaz<int> ha = new halmaz<int>(); halmaz<int> hb = new halmaz<int>(); ha. hozzaad(42); hb. hozzaad(15); ha. hozzaad(23); halmaz<int> hc = ha + hb; unió public static halmaz<T> operator +(halmaz<T> h 1, halmaz<T> h 2) { } • halmaz<int> hc = ha - hb; különbség halmaz<int> hc = ha * hb; metszet halmaz<int> hc = ha + 5; elem hozzáadása halmaz<int> hc = ha - 5; elem törlése • A kimenet mindig ÚJ objektumpéldány • Új operátort nem lehet feltalálni Szabó Zsolt, Óbudai Egyetem, 2011 V szabo. zsolt@nik. uni-obuda. hu • 1. 0 Az azonos/hasonló operátorok lehetőleg hivatkozzanak 38
Operator Overloading • Implicit konverzió, T halmaz<T> – halmaz<int> ha = 5; halmaz<string> hb="Hello"; – public static implicit operator halmaz<T>(T elso) { } • Explicit konverzió, halmaz<T> string – string valami = (string)ha; – public static explicit operator string(halmaz<T> be ) { } • Ugyanarra a típusra nem lehet mindkettő konverziót definiálni! • A kimeneti típus vagy a bemeneti típus kötelezően az operátort tartalmazó osztály! • if (ha==hb) / if (ha!=hb) / if (ha. Equals(hb)) • Equals: példányok tartalmi egyezés-vizsgálata. Sok mező/beágyazott osztály esetén inkább javasolt: Get. Hash. Code() V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 39
Tesztelés V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 40
Képek forrásai V 1. 0 Szabó Zsolt, Óbudai Egyetem, 2011 szabo. zsolt@nik. uni-obuda. hu 43