Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

AZ OOP ALAPJAI. OOP vs struktúrálatlan programozás  Az objektum-orientált programozás a klasszikus struktúrált programozásnál jóval hatékonyabb megoldást.

Hasonló előadás


Az előadások a következő témára: "AZ OOP ALAPJAI. OOP vs struktúrálatlan programozás  Az objektum-orientált programozás a klasszikus struktúrált programozásnál jóval hatékonyabb megoldást."— Előadás másolata:

1 AZ OOP ALAPJAI

2 OOP vs struktúrálatlan programozás  Az objektum-orientált programozás a klasszikus struktúrált programozásnál jóval hatékonyabb megoldást képes nyújtani a legtöbb problémára.  Az osztályok újrafelhasználásának támogatásával nagymértékben tudja csökkenteni a szoftverek fejlesztéséhez szükséges időt.  Az objektumorientált programozás abban különbözik leginkább a struktúrálatlan programozási módszerektől, hogy a programrészeket, hasonló feladatokat, de főleg hasonló feladatokon dolgozó adatokat és az azokat felhasználó metódusokat csokorba foglaljuk.  Az objektum-orientált programozás jobban igyekszik közelíteni a világban lejátszódó valódi folyamatokhoz.

3 Az OOP alapfogalmai  Osztály  Objektum, példány, egyed  Osztálydefiníció  példányváltozók  osztályváltozók  metódusok  konstruktor  destruktor  inicializáló blokk  Hozzáférési jogok  Egységbezárás  Adatelrejtés

4 Osztály létrehozása  Egy egyed egy osztály megvalósítása, más szóval példányosítása. Javaban ezt így érjük el: Object objektum = new Object()  Ilyenkor lefut az osztály konstruktora, ahol meghatározhatjuk a kezdőértékeket, inicializálhatjuk az objektumot.  Egy osztálynak lehetnek példányváltozói, illetve osztályváltozói. Előbbiből minden egyes példányosított egyedhez kerül egy-egy, míg osztályváltozóból az összes azonos osztályból példányosított egyedhez csak egy. Ugyanez érvényes az eljárásokra is.  Java esetén egy osztály definíciója és deklarációja, azaz az eljárások feje és megvalósítása nem szétválasztható, mint például C++-ban.

5 Példa - Autó  Valósítsunk meg egy Autó osztályt Javaban! package pelda002; // az osztályt tartalmazó csomag public class Auto { //az osztály kezdete // az osztály megvalósítása } //az osztály vége

6 Autó - benzinár: int - tipus: String - km_ora: double - benzin: double - ferohely: int +Auto(tipus: String, fogyasztas: double, ferohely: double) +Auto(tipus: String, fogyasztas: double, ferohely: double, km_ora: double) +költség(km: double): double +fuvar (km: double) +tankol (l: double) +toString(): String

7 Példa – Autó - változók  Ahogy C++-ban, úgy a Javában is felsorolhatunk változókat, de a Java megengedi, hogy iniciáljuk is azokat.  Változó deklarációja: [ módosítók] típus változó [inicializáció] public class Auto { static private int benzinar=250; //statikus típus private String tipus; private double benzin; private double fogyasztas; private double km_ora=0; //példa kezdőértékre private int ferohely;

8 Példa – Autó - Konstruktor  Minden osztály példányosításakor lefut egy konstruktor. Ennek neve – ahogy C++-ban is – megegyezik az osztály nevével, és nincs visszatérési értéke.  Minden osztálynak létezik konstruktora, legfeljebb az üres, mégha nem is hozzuk létre, lefut.  Konstruktorból lehet több is, túlterhelésükre ugyanaz vonatkozik, mint a függvények túlterhelésére.

9 Példa – Autó - Konstruktor public Auto(String tipus, double fogyasztas, int ferohely){ this.tipus=tipus; this.fogyasztas=fogyasztas; this.km_ora=0; this.benzin=0; this.ferohely=ferohely; } public Auto(String tipus, double fogyasztas, int ferohely, double km_ora){ this.tipus=tipus; this.fogyasztas=fogyasztas; this.km_ora=km_ora; this.benzin=0; this.ferohely=ferohely; }

10 Példa – Autó - Metódusok  Érdekesség, hogy a metódus neve megegyezhet egy változóéval is.  Az osztály metódusait, ahogy láttuk a konstruktornál, szintén túl lehet terhelni.  Metódus definíciója: [módosítók] típus Név([paraméterek]) {törzs}  Példa metódusokra:

11 • Az alábbi függvények dokumentációja és magyarázata a külön dokumentumban található public void tankol(double l){ benzin+=l; } private double benzinigeny(double km){ return ((double)km/100)*fogyasztas; } public double koltseg(double km){ return benzinigeny(km)*benzinar; } Példa – Autó - Metódusok

12 public double halad(double km) { if(benzinigeny(km)<=benzin){ benzin-=benzinigeny(km); km_ora+=km; System.out.println("Megtettunk " + km + "km utat!"); return km; } else { System.out.println("Nincs benzin " +km+ "km uthoz!"); return 0; }

13 Példa – Autó – Getter & Setter  Objektumok leírásánál legtöbbször elrejtjük a belső változókat a külvilág elől, mert pl nem akarjuk, hogy változtassák, módosítottan akarjuk megjeleníteni vagy átadni, vagy egyszerűen nem akarjuk, hogy lássák. Ezért is lettek private változók. Ilyenkor használatosak a be- és kiviteli függvények, a getterek és setterek. Most az előbbire látunk példát:  public double benzin_ora(){ return benzin; } public double km_ora() { return km_ora; }

14 Példa – Autó – String toString()  A Javában minden egyednek van egy függvénye, ami szöveges információt hordoz a példányról, ez a public String toString() függvény, amit ha nem hozunk létre, az objektumunk örököl az ősosztálytól (erről bővebben később). public String toString(){ return tipus + ", benzin: " + benzin_ora() + ", km: " + km_ora(); }

15 További osztály-elemek (említés szintjén, a példába ne foglaljuk őket):  inicializációs blokk (vagy blokkok), ami még a konstruktor előtt lefut, és azokon a változókon dolgozhat, amiket már előtte definiáltunk (mindez a az osztály törzsében, metóduson kívül). String s0; { s0 = new String("es-null"); // inic. blokkon kívül ezt nem szabadna! }  Javában a Garbage-collector elvégzi helyettünk a memória tisztítását, de néha szükség lehet valamiféle destruktor jellegű metódusra. Erre szolgál a Finalize, illetve a classFinalize metódus:  protected void Finalize() throws Throwable {}  static void classFinalize() throws Throwable {}

16 Módosítók összessége Osztály:  public: Az osztály bárki számára látható  final: Végleges, nem lehet tovább bővíteni. Az öröklődésnél lesz róla szó bővebben.  abstract: Az öröklődésnél lesz róla szó, csak bővíteni lehet, példányosítani nem.  (Üres): Üres gyakorlatilag úgy használható, mint a public, a csomagra vonatkozóan

17 Módosítók összessége Változó, illetve objektum:  public: Az objektumot használó bármely kód számára közvetlenül hozzáférhető.  protected: Private, de az alosztályok látják  private: Csak azon objektum számára elérhetők, melyben meghatározták őket.  final: Végleges, azaz konstans érték  static: Osztályváltozó, egy osztályhoz csak egy tartozik

18 Módosítók összessége Metódus esetén:  public: Az objektumot használó bármely kód számára közvetlenül hozzáférhető.  protected: Közvetlenül nem, csak egy öröklés általi alosztályon keresztül érhető el.  private: Csak azon objektum számára elérhetők, melyben meghatározták őket.  static: Példányosítás nélkül használható, (pl println fv), csak statikus változókat használhat.  final: Végleges, a leszármazott nem írhatja felül. (Öröklődésnél bővebben)  abstract: Absztrakt osztálynál használható, kötelező felülírnia, azaz megvalósítania a leszármazott osztálynak.

19 Öröklődés  Tegyük fel, hogy létre akarunk hozni:  Autót (már megvan)  Taxit  Buszt  Ez így egy kicsit sok, főleg hogy az adatok és metódusok nagy része ismétlődne.  Megoldás: bővítsük ki az Autót a Taxi jellemzőivel! = specializáljunk!

20 Öröklődés a Javában  A leszármazott osztály örökli a szülő minden tulajdonságát.  A szülő private tagjaiból is van példánya, de nem férhet hozzájuk közvetlenül (erre van a protected).  Valójában Jávában minden objektum származtatott, az ősosztály java.lang.Object kiterjesztettje.  Jávában a kiterjesztést az extend szóval jelölhetjük.  A leszármazott a szülőobjektum egyes tagjaira a super kulcsszóval hivatkozhat.  Object metódusai: equals, getClass, toString, stb

21 Az Auto osztály bővítése  Bővítsük ki az Autó osztályát, és rögtön írjuk bele az új változóinkat! public class Taxi extends Auto{ private double penztarca; private double kmdij; // függvénytest }

22 Példa – Taxi - konstruktorok  A leszármazott nem örökli a szülő konstruktorát.  Van lehetőségünk a leszármazott konstruktorának első sorában meghívni a szülő valamelyik konstruktorát a super kulcsszóval.  Ha ezt nem tesszük meg, vagy ha nem is definiálunk konstruktort, akkor is végrehajtódik a szülő üres kostruktora (ha van ilyen), mégpedig minden gyermekbeli inicializációs blokk előtt.

23 Példa – Taxi - konstruktor public Taxi(String tipus, double fogyasztas, int ferohely, double kmdij) { super(tipus, fogyasztas, ferohely); this.kmdij=kmdij; this.penztarca = 0; }

24 Elfedés, felülírás  Nyilván néhány változónak és metódusnak más szerepet szánunk az új, származtatott osztályban.  Ilyenkor felülírhatjuk, elfedhetjük a szülő azonos szignatúrájú metódusait (egyébként egyszerű túlterhelés lenne).  Taxi esetén másképp számoljuk a költséget, hiszen hozzájön még a fuvarozó kilométerdíja. Egyszerűen írjunk új eljárásokat azonos névvel, de az új funkcióval!  Itt is hivatkozhatunk a szülő metódusára (ha az már egy új fv miatt el lenne fedve) a super kulcsszóval.  A toString() függvényünket is úgy módosítsuk, hogy az már kiírja a fuvarozó pénztárcájának tartalmát is!

25 Példa – Taxi  Írjuk meg a Taxi osztályt!  A költség számításánál vegyük figyelembe a kilométerdíjat!  A halad függvényt hagyjuk meg, mellé hozzunk létre egy fuvaroz függvényt, ahol adjuk hozzá a taxis pénztárcájához a kilométerdíjból beszedett összeget is.  A toString() metódus írja ki egyrészt az Autó adatait, de tegye hozzá a taxis pénztárcájának tartalmát is.

26 public double koltseg(double km){ return super.koltseg(km)+kmdij*km; } public void tankol(int l){ benzin+=l; penztarca-=l*benzinar; } public String toString(){ return super.toString()+", a fuvarozo penze: "+penztarca; }

27  A halad(int km) függvényt ne írjuk felül, mert két fuvar közt egyszerű autóként halad a taxis: public double fuvar(double km){ if(halad(km)==km){ //a halad(int km)-t nem irtuk felul. penztarca+=koltseg(km); return km; } else return 0; }

28  Költség/fő (ha többen taxizunk, olcsóbb) public double koltseg_per_fo(double km, int fo){ if(fo>ferohely+1){ System.out.println("Tobb utas, mint ferohely, ha rendor jon, nagyon draga lesz!"); return 0; } else return koltseg(km)/fo; }

29 Kész a Taxi osztály  De még nem működhet teljesen:  Az Autó tagváltozóinak mindig private a módosítójuk, változtassuk meg protectedre, hogy tudjuk őket használni!  Hozzunk létre egy futtató osztályt main()-nel! public class runAuto { public static void main(String[] args){ Auto lada = new Auto("Lada", 10, 5); Taxi daewoo = new Taxi("Daewoo", 7, 5, 200); lada.tankol(40); lada.halad(15); // Megtettunk 15.0km utat! System.out.println(lada.toString()); // Lada, benzin: 38.5, km: 15.0 daewoo.tankol(30); daewoo.halad(40); // Megtettunk 40.0km utat! System.out.println(daewoo.koltseg_per_fo(15, 4));// daewoo.fuvar(200); System.out.println(daewoo.toString()); //Daewoo, benzin: 13.2, km: 240.0, a fuvarozo penze:

30 Ízelítő a következő óra anyagából  Polimorfizmus: Auto tata = new Taxi("Tata (indiai automarka)", 9, 4, 250); // létrehoztunk egy autót, ami egyébként egy taxi. tata.tankol(18); // Taxival vettunk 18.0l benzint! // tata.fuvar(100); // helytelen! tata.halad(100); // Megtettunk 100.0km utat! System.out.println(tata.toString()); // Tata (indiai automarka), benzin: 9.0, km: 100.0, a fuvarozo penze:

31 Véglegesítés  Hozzuk létre a Busz osztályt a Taxi osztálybol!  A buszon egy vonaljeggyel lehet utazni, szintén van kilométerdíj, amit a sofőr kap.  A költség marad ugyanúgy, ahogy a taxinál volt, ellenben a fuvar esetében az üzemeltető cég pénztárcáját tekintsük, azaz a jegyárból vontjuk ki a buszvezető díját is!  Az osztály legyen végleges, azaz már ne lehessen szülő (final)  Az alábbi osztályokat valósítsuk meg:  public Busz(String tipus, double fogyasztas, int ferohely, double kmdij)  public double fuvar(double km)  public double fuvar(double km, int fo)  public double Haszon(double km, int fo)  public double koltseg_per_fo(double km, int fo)

32 Busz megvalósítás public final class Busz extends Taxi { private int jegyar = 230; /** * Busz konstruktora tipus A busz márkája fogyasztas //A busz fogyasztása ferohely // Férőhelyek száma kmdij //A buszvezető bére kilométerenként */ public Busz(String tipus, double fogyasztas, int ferohely, double kmdij){ super(tipus,fogyasztas, ferohely, kmdij); }

33 Busz megvalósítás /** * A fuvar ára egy vonaljegy. Most csak egy embert viszunk * csak hogy felul tudjuk irni a Taxi fuggvenyet */ public double fuvar(double km){ if(halad(km)==km){ //a halad(int km)-t nem irtuk felul. penztarca+=jegyar – km_dij*km; return km; } else return 0; }

34 Busz megvalósítás /** * Fuvar több főre. km Megtett út fo Utasok száma Megtett kilométerek száma */ public double fuvar(double km, int fo){ if(halad(km)==km){ penztarca+=fo*jegyar - km*kmdij; return km; } else return 0; }

35 Busz megvalósítása /** * A fuvarozó cég összköltsége. Tegyük fel, hogy * az utasok végig utazták az utat. km A megtett kilométerek száma fo Utasok száma Költség forintban */ public double Haszon(double km, int fo){ return fo*jegyar - koltseg(km); }

36 /** * Akárhányan is utazunk akármennyit, csak egy vonaljegyet veszünk. */ public double koltseg_per_fo(double km, int fo){ return jegyar; }

37 Általánosítás  A specializálással ellentétes fejlesztés az általánosítás.  Tegyük fel, hogy létre akarok hozni egy kerékpár típust. Szintén lenne néhány közös jellemzője az autóval.  Hozzunk létre egy jármű osztályt, de úgy, hogy azt ne lehessen példányosítani, azaz legyen abstract!  Ilyenkor amelyik függvényt abstract jelzővel illetjük, azt az utódnak muszáj felülírnia. Ez esetben a halad(), illetve a költség() metódus lehet ilyen.  Az autóból természetesen át kell tenni néhány változót, azokat, amik a kerékpárral, illetve általánosságban egy járművel egyeznek!  Valósítsuk meg a járművet!

38 public abstract class Jarmu { protected String tipus; protected double km_ora; protected int ferohely; // Haladást megvalósító metódus, absztrakt public abstract double halad(double km); // Költséget kiszámoló metódus, absztrakt public abstract double koltseg(double km); // Egy megvalósított metódus, kiírja a nevét és a kmórát. public String toString(){ return this.tipus+ ", " + km_ora + " km"; }

39 Kerékpár megvalósítása  Írjuk meg a kerékpár osztályát!  A költség legyen 0! (ezért is szeretjük a kerékpárt)   A haladást csak a kilométeróra növekedése kövesse!  A toString() a típust és a kilométerórát írja ki!

40 public final class Kerekpar extends Jarmu { public Kerekpar( String tipus){ // Egy kerékpár this.tipus=tipus; this.km_ora=0; this.ferohely=1; } public double halad(double km) { // A halad fv. this.km_ora+=km; return 0; } public double koltseg(double km) { // Adott utra adott koltseg. return 0; }

41 Vége! (majdnem)  A feladatok megoldásai megtekinthetők a digitus../stuat/progny/ mappában.  Házi feladat:  Hozzunk létre egy osztályhierarchiát, melyben ingatlanokat reprezentálunk.  Legyen egy absztrakt Ingatlan osztály, ahol az ingatlan területe, címe és bérleti díja van, továbbá egy metódust, ami az éves költségeket számolja ki.  Írjunk egy Lakás osztályt, ahol a lakók számát is tároljuk, ők a lakásért fizetnek adót, illetve rezsit.  Írjunk egy Kollégium osztályt, mely a Lakásból öröklődik, számoljunk az állami támogatással és számoljuk ki az egy főre eső költségeket is.  Végül valósítsunk meg egy Iroda osztályt is, ahol tároljuk a cég nevét, a költségek számításánál pedig figyelembe vesszük az adót is.  Összes osztálynál legyen aktuális String toString osztály!


Letölteni ppt "AZ OOP ALAPJAI. OOP vs struktúrálatlan programozás  Az objektum-orientált programozás a klasszikus struktúrált programozásnál jóval hatékonyabb megoldást."

Hasonló előadás


Google Hirdetések