OOP: Java 7.Gy: Öröklődés, referenciák 37/1 B ITv: MAN 2019.03.26
Öröklődés Egységbezárás (az egyik OOP alapelv) : az adatokat és rajtuk végzett műveleteket egy egységként kezeljük, ez az egység az osztály. Öröklődés (másik OOP alapelv): osztályok között valósul meg, egy szülő (ős, base, parent) és gyerek (leszármazott, derived) között. Az öröklődés során a gyerek osztály örökli a szülőjének tulajdonságait és viselkedését. Ez jó dolog, mert nem kell újra írnunk őket, viszont a szülőtől örökölt egyes metódusokat speciálisabban is megvalósíthatjuk, felülírhatjuk őket (override), vagy akár újakat is definiálhatunk. Javaban csak egyszeres öröklődés van! Ez azt jelenti, hogy egy osztálynak nem lehet kettő, vagy több szülőosztálya. Azt viszont nem zárja ki, hogy egy osztálynak több gyerek osztálya legyen, vagy hogy a gyerek osztálynak lehessenek saját gyerek osztályai. 37/2
A Torta osztály kódja public class Torta { protected int szelet; private String iz; public String getiz() { return iz; public void setiz(string iz) { this.iz = iz; public Torta(int szelet, String iz) { this.szelet = szelet; this.iz = iz; public void info() { System.out.println("Ez a torta " + this.iz + " ízű, és " + this.szelet + " szeletes."); 37/3 Alap Torta osztály, már kész van. Szeretnénk felhasználni a SzülinapiTorta osztályhoz, melyben legyen gyertyák száma adattag, és egy kívánságot teljesítő metódus.
Öröklődés A szülő adattagjai és metódusai öröklődnek, a konstruktora nem! Két fontos kulcsszó: extends: ezzel a kulcsszóval adhatjuk meg az öröklődést Kiterjesztést, kibővítést, megnyújtást jelent Használata mindig (gyerek extends szülő formátumú): public class SzulinapiTorta extends Torta super: a gyerek osztályból hivatkozhatunk a szülőre, annak adattagjaira (amiket látunk) és metódusaira is, ezeket super.szulometodusanakneve()-szerű parancsokkal érhetjük el. A szülő konstruktorát a super kulcsszó metódusként történő használatával érjük el: super(szelet, iz); 37/4
37/5
A Torta osztály kódja public class SzulinapiTorta extends Torta { private int gyertyakszama; public SzulinapiTorta(int szelet, String iz, int gyertyakszama) { 37/6 super(szelet, iz); this.gyertyakszama = gyertyakszama; public void kivansagotteljesit() { System.out.println("Kívánságod teljesült!"); A gyerek konstruktorából hívjuk a szülő konstruktorát. Ez mindig a legelső sor a konstruktorban! Új metódus, csak ebben az osztályban használható! public void info() { System.out.println("Ez a szülinapi torta " + this.getiz()+ " ízű, és "+ this.szelet + " szeletes." + this.gyertyakszama + " db gyertya van rajta"); Felüldefiniált metódus, attól függ, hogy mit ír ki, hogy melyik osztályból hívjuk!
Öröklődés Polimorfizmus (többalakúság) A gyerek osztály egy példánya kezelhető a szülő egy példányaként is, ezért egy SzülinapiTorta objektumot tárolhatunk Torta példányként public class TortaProgram { public static void main(string[] args) { Torta csokitorta = new SzulinapiTorta(15, "csoki", 9); Ha ős típusként tárolunk egy gyerek típusú objektumot, akkor a gyerek típusú objektum úgy viselkedik, mintha ős típusú lenne, ezért a gyerek osztályban definiált metódusai nem láthatók, nem használhatók! Torta csokitorta = new SzulinapiTorta(15, "csoki", 9); csokitorta.kivansagotteljesit(); Nem működik, mert egy közönséges Torta nem tud kívánságot teljesíteni! 37/7
Öröklődés Polimorfizmus (többalakúság) Torta[] cukraszda = new Torta[3]; cukraszda[0] = new Torta(20, "csokis-meggyes"); cukraszda[1] = new Torta(12, "epres"); cukraszda[2] = new SzulinapiTorta(12, "karamell", 12); for (Torta t : cukraszda) t.info(); Egy ős típusú tömbben vegyesen tárolunk ős és gyerek típusokat Ha meghívjuk az elemekre az info() metódust, amelyik létezik az ős osztályban, de felül van definiálva a gyerek osztályban (vagyis mindkét osztályra használható), annak megfelelő adatokat fog kiírni, amelyik osztályba tartozik az adott tömbelem: Ez a torta csokis-meggyes ízű, és 20 szeletes. Ez a torta epres ízű, és 12 szeletes. Ez a szülinapi torta karamell ízű, és 12 szeletes.12 db gyertya van rajta 37/8
Öröklődés Polimorfizmus (többalakúság) Torta[] cukraszda = new Torta[3]; cukraszda[0] = new Torta(20, "csokis-meggyes"); cukraszda[1] = new Torta(12, "epres"); cukraszda[2] = new SzulinapiTorta(12, "karamell", 12); for (Torta t : cukraszda) t.info(); Ha az info() metódus csak az ősosztályban (Torta) lenne definiálva, működne a kód, és minden tömbelemre egyforma infót kapnánk. Ha az info() metódus csak a gyerek (SzülinapiTorta) osztályban lenne definiálva, nem fordulna le a kód, és a következő hibaüzenetet kapnánk: Exception in thread "main" java.lang.error: Unresolved compilation problem: The method info() is undefined for the type Torta 37/9
37/10
Feladat 1. Definiáljon saját csomagban (myproducts) Áru (Product) osztályt. Adattagjai: név, nettó ár (egész), áfakulcs (egész, százalék) Konstruktora: mindhárom adat megadásával inicializálja az adattagokat. Metódusai: - Számítsa ki a bruttóárát egy árunak (egész, kerekítve). - Egy sztringbe összefűzve adja vissza az áru nevét és a bruttó árát. Definiálja felül az Object osztálybeli tostring metódust! - Növelje meg az áru nettó árát a paraméterben megadott százalékos értékkel (egész). - Hasonlítsa össze két áru bruttó árát. 1-et adjon vissza, ha az áru drágább mint a paraméterben megadott; -1-et ha olcsóbb és 0-t ha azonos árúak. 37/11
1 37/12
A Product osztály kódja package myproducts; public class Product { private String name; private int netprice; //Nettó ár private int taxpercent; //Áfakulcs taxkey :) public Product(String name, int netprice, int taxpercent) { //super(); this.name = name; this.netprice = netprice; this.taxpercent = taxpercent; public int getpricewithtax() { return netprice+(netprice*taxpercent/100); 37/13
A Product osztály kódja @Override Product [name = Retek, price = 254] public String tostring() { return "Product [name = " + name + ", price = " + getpricewithtax() + "]"; public void increaseprice(int percentage) { this.netprice = netprice+(netprice*percentage/100); public int ismoreexpensivethan(product product) { if (this.getpricewithtax() > product.getpricewithtax()) { return 1; else if (this.getpricewithtax()==product.getpricewithtax()){ return 0; else return -1; 37/14
Feladat Készítsen az Áru osztállyal azonos csomagban Kenyér osztályt, amely az Áru leszármazottja. Adattagja: mennyiség (valós, pl. 0.75) Konstruktora: négy paraméterben kapott adattal inicializálja az objektumot. Metódusai: Definiálja felül a tostring metódust. Az ősosztályban definiált metódushoz képest fűzze hozzá az egységárat (bruttóár/mennyiség). Adja vissza a mennyiséget. Hasonlítsa össze két kenyér egységárát. Az osztályszintű metódus akkor adjon vissza igazat, ha a paraméterként kapott két Kenyér közül az elsőnek nagyobb az egységára. 37/15
A Bread osztály kódja package myproducts; public class Bread extends Product { double amount; //Mennyiség public Bread(String name, int netprice, int taxpercent, double amount) { super(name, netprice, taxpercent); this.amount = amount; @Override Bread [Product [name = Rozs, price = 285], unit price = 380] public String tostring() { return "Bread [" + super.tostring() + ", unit price = " + getunitprice() + "]"; public int getunitprice() { return (int)(getpricewithtax()/amount); 37/16
A Bread osztály kódja public double getamount() { return amount; public static boolean compareunitprice(bread bread1, Bread bread2) { if (bread1.getunitprice() > bread2.getunitprice()) { return true; else return false; public boolean hasgreaterunitprice(bread bread) { if (this.getunitprice() > bread.getunitprice()) { return true; else return false; 37/17
A Bread osztály kódja public boolean hasgreaterprice(bread bread) { if (this.getpricewithtax() > bread.getpricewithtax()) { return true; else return false; 37/18
Feladat Készítsen egy futtatható osztályt a myproducts.producttest alcsomagjában. Ebben hozzon létre egy Áru és egy Kenyér objektumot. Írja ki az adataikat, és hasonlítsa össze az árukat. Melyik osztály metódusával lehetséges az összehasonlítás? Hozzon létre még egy Kenyér típusú objektumot, de ennek a referenciáját egy Áru típusú változóban tárolja (neve: product2). Próbálja ki, hogy a "product2" referenciára meghívva milyen eredményt ad a tostring metódus. Meg tudja-e hívni ezen a referencián keresztül a Kenyér mennyiségét visszaadó metódust? Hozzon létre még egy Kenyér példányt (neve: bread2) és a "product2" referenciával hivatkozott másik Kenyérrel összehasonlítva a nagyobb egységárút kell kiírni (konvertálásra lesz szükség). 37/19
Az breadtest osztály kódja package myproducts.producttest; import myproducts.*; public class breadtest { public static void main(string[] args) { // TODO Auto-generated method stub Product product= new Product("Kakaó", 200, 27); Bread bread= new Bread("Rozs", 250, 14, 0.75); System.out.println(product + "\n" + bread); //Árak összehasonlítása: System.out.println(product.isMoreExpensiveThan(bread)); //! System.out.println(bread.hasGreaterPrice(product); 37/20
Az breadtest osztály kódja Product product2 = new Bread("Fehér", 200, 14, 1); //tostring metódus hívása System.out.println(product2); //! System.out.println(product2.getAmount()); Bread bread2 = new Bread("Fini", 400, 14, 1); if(bread.compareunitprice((bread)product2, bread2)) { System.out.println(product2); else System.out.println(bread2); 37/21 Product [name = Kakaó, price = 254] Bread [Product [name = Rozs, price = 285], unit price = 380] -1 Bread [Product [name = Fehér, price = 228], unit price = 228] Bread [Product [name = Fini, price = 456], unit price = 456]
Feladat A korábban saját csomagban definiált Könyv osztály (mybooks.book) leszármazottjaként készítsen egy másik csomagban KönyvStílus osztályt. Adattagjai: stílus (szöveg) Konstruktora: minden adatát paraméterben kapott adatokkal inicializálja. Metódusai: Adja vissza a stílust. Definiálja felül az ősosztálybeli String-et visszaadó metódust úgy, hogy az ősbeli sztringhez fűzze hozzá a stílust is. 37/22
A Book osztály kódja package mybook; import java.time.localdate; //6. gyakorlat házi feladat public class Book { private String author; private String title; private int price; private final int yearofpublication; private int pages; private String publisher = "Móra"; public Book(String author, String title, int price, int pages) { this.author = author; this.title = title; this.price = price; this.yearofpublication = LocalDate.now().getYear(); this.pages = pages; public Book(String author, String title) { this(author, title, 2500, 100); 37/23
A Book osztály kódja @Override public String tostring() { return author + ": " + title + ", " + yearofpublication + ", " + price + " Ft, pp " + pages + ", " + publisher; public static Book getlonger(book book1, Book book2) { if (book1.getpages() >= book2.getpages()) return book1; else return book2; public boolean hasevenpages() { if (this.getpages()%2==0) return true; else return false; public void increaseprice(int percentage) { price += Math.round(price*(float)percentage/100); //+ getters, setters 37/24
A BookStyle osztály kódja package mystyle; import mybook.book; public class BookStyle extends Book{ String style; public BookStyle(String author, String title, int price, int pages, String style) { super(author, title, price, pages); this.style = style; public String getstyle(){ return style; @Override public String tostring() { return getauthor() + ": " + gettitle() + ", " + getyearofpublication() + ", " + getprice() + " Ft, pp " + getpages() + ", " + getpublisher() + "\nstílusa: " + style; 37/25
Feladat Készítsen egy futtatható osztályt a KönyvStílus-t magában foglaló csomag alcsomagjában. Ebben olvasson be n darab stílusos könyvet egy tömbbe. N-et ellenőrzött módon olvassa be (1 és 10 közötti érték). Számolja meg hányféle különböző stílusú könyv szerepel a tömbben. Írja ki a "Scifi" stílusú könyvek adatait. Számítsa ki a "Scifi" stílusú könyvek átlagárát. A String-ek egyezésének vizsgálatára használja a String osztály metódusát: boolean equalsignorecase(string anotherstring) 37/26
A BookStyleTest osztály kódja package mystyle.test; import java.util.scanner; import mystyle.bookstyle; public class BookStyleTest { public static void main(string[] args) { Scanner input = new Scanner(System.in); System.out.println("Please enter the number of books!"); int numberofbooks= readint(); BookStyle[] books= new BookStyle[numberOfBooks]; for(int i=0; i<books.length; i++) { System.out.println((i+1) + ". Szerző: "); String author = input.nextline(); System.out.println((i+1) + ". Cím: "); String title = input.nextline(); System.out.println((i+1) + ". Ár: "); int price = input.nextint(); System.out.println((i+1) + ". Oldalszám: "); int pages = input.nextint(); input.nextline(); System.out.println((i+1) + ". Stílus: "); String style = input.nextline(); books[i] = new BookStyle(author, title, price, pages, style); 37/27
A BookStyleTest osztály kódja for(bookstyle book : books) { System.out.println(book); System.out.println(countStyles(books)); String searchstyle = "scifi"; listbooks(books, searchstyle); System.out.println(searchStyle + " könyvek átlagára: " + avgprice(books, searchstyle)); public static int readint() { Scanner input = new Scanner(System.in); int n; do { System.out.println("Enter a number"); while (!input.hasnextint()) { System.out.println("That's not a number"); input.next(); n = input.nextint(); while(n<1 n>10); return n; 37/28
A BookStyleTest osztály kódja public static int countstyles(bookstyle[] books) { //Az első könyv stílusa az első stílus int counter = 1; for(int i=1; i<books.length; i++) { boolean found = false; for(int j=i-1; j>=0; j--) { if (books[i].getstyle().equalsignorecase(books[j].getstyle())) { found = true; break; else continue; if (!found) counter++; return counter; public static void listbooks(bookstyle[] books, String style) { for(bookstyle book : books) { if(book.getstyle().equalsignorecase(style)) System.out.println(book); 37/29
A BookStyleTest osztály kódja public static double avgprice(bookstyle books[], String style) { double sumprice = 0; int counter = 0; for(bookstyle book : books) { if(book.getstyle().equalsignorecase(style)) { sumprice += book.getprice(); counter++; return sumprice/counter; 37/30
Házi feladat Készítsen saját csomagban Személy osztályt (pl. mypersons.person). Adattagjai: név, kor Konstruktora: két paraméterben kapott értékkel inicializálja az adattagokat Metódusai: Getter metódusok az adattagok lekérdezésére. A Személy adatait String-ben összefűző és ezzel visszatérő metódus. Adjon vissza igazat, ha a paraméterben megadott személy életkora kisebb. 37/31
Házi feladat Készítsen ugyanebben a csomagban Gyermek és Felnőtt osztályokat a Személy osztály leszármaztatásával. Adattagjaik: iskola (a Gyermek osztályban, String) ; munkahely (a Felnőtt osztályban, String) Konstruktoraik: három paraméterben kapott értékkel inicializálják az adattagokat Metódusaik: Mindkét osztályban definiálja felül az adatokat String-ben összefűző öröklött metódust. Adja vissza a Gyermek iskoláját, ill. a Felnőtt munkahelyét. 37/32
Házi feladat Készítsen futtatható osztályt az előbb definiált osztályokat magába foglaló csomag alcsomagjában (pl. mypersons.test.persontest). Ebben deklaráljon két személy típusú referenciát, amelyek értéke a személy beolvasó függvény által visszaadott referencia lesz. Írjon személy beolvasó függvényt, amelyben beolvassa egy személy adatait (név, kor). A referencia dinamikus típusát ellenőrzött módon határozza meg (ha 18 év alatti akkor Gyermek, egyébként Felnőtt), majd értelemszerűen olvassa be a Gyermek iskoláját ill. a Felnőtt munkahelyét. Hozza létre az objektumot, majd térjen vissza a referenciájával. A main metódusban kérdezze le a létrejött objektumok típusát (instanceof) és irassa ki az adataikat. 37/33
Házi feladat A Felnőtt osztály kiterjesztéseként hozzon létre ugyanabban a csomagban egy Alkalmazott osztályt (pl. mypersons.employee). Adattagja: fizetés (egész), nyugdíjkorhatár (osztályszintű, egész: értéke 65) Konstruktora: négy paraméterben kapott értékkel inicializálja az adattagokat (név, életkor, munkahely, fizetés). Metódusai: Adja vissza a fizetést. Definiálja felül az adatokat String-ben összefűző öröklött metódust. 37/34
Házi feladat Készítsen új futtatható osztályt a mypersons.test alcsomagban, és másolja ide az előző futtatható osztályát. Amikor meghatározza a Személy típusúra deklarált referenciák dinamikus típusát, a Felnőttek esetén ellenőrizze a munkahely értékét: csak akkor lehet Alkalmazott, ha a munkahely nem üres (nem minden felnőtt alkalmazott). Ha alkalmazottról van szó, akkor a fizetését is olvassa be. Ezek után kérdezze le a létrejött objektumok típusát (instanceof) és irassa ki az adataikat. Annak vizsgálata, hogy a munkhely értéke (String) üres-e: workplace.isempty() workplace.length() == 0 workplace.equals("") 37/35
Házi feladat Módosítsa úgy a futtatható osztályban a main metódus kódját, hogy hozzon létre egy n elemű Személy tömböt. N értékét olvassa be ellenőrzött módon. Az adatok beolvasásakor dőljön el, hogy az adott személy Gyermek, Felnőtt, vagy Alkalmazott. Majd életkoruk szerint növekvően rendezve írja ki az adataikat. Használja a minimum kiválasztásos rendező eljárást. 37/36
VÉGE VÉGE 37/37