Programiranje

Dedovanje v Javi, 1. del: Ključna beseda extends

Java podpira ponovno uporabo razreda z dedovanjem in sestavljanjem. Ta dvodelna vadnica vas uči, kako uporabljati dedovanje v svojih programih Java. V prvem delu boste izvedeli, kako uporabljati podaljša ključna beseda za izpeljavo podrejenega razreda iz nadrejenega razreda, priklic konstruktorjev in metod nadrejenega razreda in preglasitev metod. V 2. delu boste obiskali java.lang.Object, ki je Javin nadrazred, iz katerega podeduje vsak drugi razred.

Če želite dokončati učenje o dedovanju, si oglejte moj namig Java, ki pojasnjuje, kdaj uporabiti sestavo in dedovanje. Izvedeli boste, zakaj je sestava pomemben dodatek dedovanju in kako jo uporabljati za zaščito pred težavami z enkapsulacijo v vaših programih Java.

prenos Prenesite kodo Prenesite izvorno kodo, na primer programe v tej vadnici. Ustvaril Jeff Friesen za JavaWorld.

Dedovanje Java: Dva primera

Dedovanje je programska konstrukcija, ki jo uporabljajo razvijalci programske opreme je-a odnosi med kategorijami. Dedovanje nam omogoča, da iz bolj splošnih izpeljemo bolj specifične kategorije. Bolj specifična kategorija je bolj splošne kategorije. Na primer, tekoči račun je nekakšen račun, na katerem lahko opravite pologe in dvige. Podobno je tovornjak vrsta vozila, ki se uporablja za vleko večjih predmetov.

Dedovanje se lahko spusti skozi več ravni, kar vodi do vedno bolj specifičnih kategorij. Kot primer je na sliki 1 prikazan podedovanje avtomobila in tovornjaka od vozila; karavan, ki podeduje iz avtomobila; in smetarsko vozilo, ki ga podeduje od tovornjaka. Puščice kažejo od bolj specifičnih "podrejenih" kategorij (spodaj navzdol) do manj specifičnih "nadrejenih" kategorij (višje navzgor).

Jeff Friesen

Ta primer ponazarja samostojna dediščina v katerem podrejena kategorija podeduje stanje in vedenja iz ene neposredne nadrejene kategorije. V nasprotju, večkratno dedovanje omogoča podrejeni kategoriji podedovati stanje in vedenje iz dveh ali več neposrednih starševskih kategorij. Hierarhija na sliki 2 prikazuje večkratno dedovanje.

Jeff Friesen

Kategorije so opisane po razredih. Java podpira enojno dedovanje prek podaljšek razreda, v katerem en razred neposredno podeduje dostopna polja in metode drugega razreda z razširitvijo tega razreda. Java pa ne podpira večkratnega dedovanja prek razširitve razreda.

Ko si ogledujete hierarhijo dedovanja, lahko večkratno dedovanje enostavno zaznate s prisotnostjo diamantnega vzorca. Slika 2 prikazuje ta vzorec v kontekstu vozila, kopenskega vozila, vodnega vozila in lebdenja.

Ključna beseda extends

Java podpira razširitev razreda prek podaljša ključna beseda. Ko je prisoten, podaljša določa razmerje med staršem in otrokom med dvema razredoma. Spodaj uporabljam podaljša vzpostaviti odnos med razredi Vozilo in Avtoin nato med račun in Varčevalni račun:

Seznam 1. podaljša ključna beseda določa razmerje med staršem in otrokom

class Vehicle {// izjave članov} class Car razširja Vehicle {// podeduje dostopne člane iz Vehicle // zagotavlja lastne izjave članov} class Account {// izjave članov} class SavingsAccount podaljša račun {// podeduje dostopne člane iz Account // zagotavlja izjave lastnih članov}

The podaljša ključna beseda je navedena za imenom razreda in pred imenom drugega razreda. Ime razreda prej podaljša identificira otroka in ime razreda po podaljša identificira starša. Po tem ni mogoče določiti več imen razredov podaljša ker Java ne podpira večkratnega dedovanja na osnovi razredov.

Ti primeri kodificirajo razmerja is-a: Avtoje specializirano Vozilo in Varčevalni računje specializirano račun. Vozilo in račun so znani kot osnovni razredi, razredi staršev, ali superrazredi. Avto in Varčevalni račun so znani kot izpeljani razredi, otroški razredi, ali podrazredi.

Zaključni pouk

Lahko razglasite razred, ki ga ne bi smeli razširiti; na primer iz varnostnih razlogov. V Javi uporabljamo dokončno ključno besedo, da preprečite razširitev nekaterih razredov. Preprosto pred glavo glave preda dodajte dokončno, kot v geslo končnega razreda. Glede na to izjavo bo prevajalnik sporočil napako, če bo nekdo poskusil razširiti Geslo.

Otroški razredi podedujejo dostopna polja in metode od svojih starševskih razredov in drugih prednikov. Nikoli ne podedujejo konstruktorjev. Namesto tega otroški razredi razglasijo svoje konstruktorje. Poleg tega lahko prijavijo svoja polja in metode, s katerimi jih ločijo od staršev. Razmislite o seznamu 2.

Seznam 2. An račun razred staršev

razred Račun {ime zasebnega niza; zasebni dolg znesek; Račun (ime niza, dolg znesek) {this.name = ime; setAmount (znesek); } neveljavna vloga (dolg znesek) {this.amount + = znesek; } String getName () {return ime; } long getAmount () {vrnjeni znesek; } void setAmount (dolg znesek) {this.amount = znesek; }}

Seznam 2 opisuje generični razred bančnega računa, ki ima ime in začetni znesek, ki sta oba nastavljena v konstruktorju. Uporabnikom omogoča tudi polog. (Izplačila lahko izvedete tako, da položite negativne zneske denarja, vendar bomo to možnost prezrli.) Upoštevajte, da je treba ob ustvarjanju računa nastaviti ime računa.

Predstavljanje valutnih vrednosti

štetje penijev. Morda raje uporabite dvojno ali a plovec za shranjevanje denarnih vrednosti, vendar to lahko privede do netočnosti. Za boljšo rešitev razmislite BigDecimal, ki je del standardne knjižnice razredov Java.

Seznam 3 predstavlja a Varčevalni račun otroški razred, ki razširja svoj račun razred staršev.

Seznam 3. A Varčevalni račun otroški razred podaljša svoj račun razred staršev

razred SavingsAccount razširja račun {SavingsAccount (dolg znesek) {super ("prihranek", znesek); }}

The Varčevalni račun razred je nepomemben, ker mu ni treba prijaviti dodatnih polj ali metod. Deklarira pa konstruktor, ki inicializira polja v njem račun superrazred. Inicializacija se zgodi, ko računKonstruktor se pokliče prek Jave super ključni besedi, ki ji sledi seznam argumentov v oklepaju.

Kdaj in kje poklicati super ()

Tako kot to () mora biti prvi element v konstruktorju, ki pokliče drugi konstruktor v istem razredu, super () mora biti prvi element v konstruktorju, ki pokliče konstruktor v svojem superrazredu. Če kršite to pravilo, bo prevajalnik sporočil napako. Prevajalnik bo sporočil tudi napako, če zazna a super () priklic metode; samo kdaj super () v konstruktorju.

Seznam 4 se še razširja račun z Preverjanje računa razred.

Seznam 4. A Preverjanje računa otroški razred podaljša svoj račun razred staršev

razred CheckingAccount podaljša račun {CheckingAccount (dolg znesek) {super ("preverjanje", znesek); } neveljaven umik (dolg znesek) {setAmount (getAmount () - znesek); }}

Preverjanje računa je malo bolj bistven kot Varčevalni račun ker razglaša a dvigniti() metoda. Upoštevajte klice te metode setAmount () in getAmount (), ki Preverjanje računa podeduje od račun. Ne morete neposredno dostopati do znesek polje v račun ker je to polje prijavljeno zasebno (glej seznam 2).

super () in konstruktor brez argumentov

Če super () ni določen v konstruktorju podrazreda in če nadrazred ne deklarira brez argumenta konstruktor, bo prevajalnik sporočil napako. To je zato, ker mora konstruktor podrazreda poklicati a brez argumenta konstruktor superklase, ko super () ni prisoten.

Primer hierarhije razredov

Ustvaril sem AccountDemo razred, ki vam omogoča, da preizkusite račun razredna hierarhija. Najprej si oglejte AccountDemoizvorna koda.

Seznam 5. AccountDemo prikazuje hierarhijo razreda računov

class AccountDemo {public static void main (String [] args) {SavingsAccount sa = nov SavingsAccount (10000); System.out.println ("ime računa:" + sa.getName ()); System.out.println ("začetni znesek:" + sa.getAmount ()); sa.depozit (5000); System.out.println ("nov znesek po vplačilu:" + sa.getAmount ()); CheckingAccount ca = nov CheckingAccount (20000); System.out.println ("ime računa:" + ca.getName ()); System.out.println ("začetni znesek:" + ca.getAmount ()); približno depozit (6000); System.out.println ("nov znesek po vplačilu:" + ca.getAmount ()); približno umik (3000); System.out.println ("nov znesek po dvigu:" + ca.getAmount ()); }}

The glavni () metoda iz seznama 5 najprej prikaže Varčevalni račun, potem Preverjanje računa. Ob predpostavki Account.java, SavingsAccount.java, CheckingAccount.java, in AccountDemo.java izvorne datoteke so v istem imeniku, za prevajanje vseh teh izvornih datotek izvedite enega od naslednjih ukazov:

javac AccountDemo.java javac * .java

Za zagon aplikacije izvedite naslednji ukaz:

java AccountDemo

Upoštevati morate naslednje rezultate:

ime računa: začetni znesek prihranka: 10000 nov znesek po vplačilu: 15000 ime računa: preverjanje začetnega zneska: 20000 nov znesek po vplačilu: 26000 nov znesek po dvigu: 23000

Preglasitev metode (in preobremenitev metode)

Podrazred lahko preglasiti (zamenjati) podedovano metodo, tako da se namesto nje pokliče različica metode podrazreda. Preglasitvena metoda mora navesti isto ime, seznam parametrov in vrsto vrnitve kot metoda, ki jo preglasite. Za dokaz sem razglasil natisni () metoda v Vozilo razred spodaj.

Seznam 6. Prijava a natisni () metoda, ki jo je treba preglasiti

razred Vozilo {private String make; model zasebnega niza; zasebno int leto; Vozilo (znamka niza, model niza, int leto) {this.make = znamka; this.model = model; this.year = leto; } String getMake () {return make; } String getModel () {return model; } int getYear () {vrnjeno leto; } void print () {System.out.println ("Make:" + make + ", Model:" + model + ", Leto:" + leto); }}

Nato preglasim natisni () v Tovornjak razred.

Seznam 7. Preglasitev natisni () v Tovornjak podrazred

razred Truck podaljša vozilo {zasebna dvojna tonaža; Tovornjak (znamka niza, model niza, int leto, dvojna tonaža) {super (znamka, model, leto); this.tonnage = tonaža; } double getTonnage () {povratna tonaža; } void print () {super.print (); System.out.println ("Tonaža:" + tonaža); }}

Tovornjakje natisni () metoda ima enako ime, vrsto vrnitve in seznam parametrov kot Voziloje natisni () metoda. Upoštevajte tudi to Tovornjakje natisni () metoda najprej pokliče Voziloje natisni () metoda s predpono super do imena metode. Pogosto je dobro najprej izvršiti logiko superrazreda, nato pa logiko podrazreda.

Klicanje metod superrazreda iz metod podrazredov

Če želite iz nadrejene metode priklicati metodo superklase, pred metodo predpona dodajte rezervirano besedo super in operaterja dostopa do člana. V nasprotnem primeru boste na koncu rekurzivno poklicali nadrejeno metodo podrazreda. V nekaterih primerih bo podrazred prikrilzasebno polja superrazreda z razglasitvijo istoimenskih polj. Lahko uporabiš super in operaterja dostopa za dostop dozasebno polja superrazreda.

Za dopolnitev tega primera sem izvlekel a VehicleDemo razredov glavni () metoda:

Tovornjak tovornjak = nov tovornjak ("Ford", "F150", 2008, 0,5); System.out.println ("Make =" + truck.getMake ()); System.out.println ("Model =" + truck.getModel ()); System.out.println ("Leto =" + truck.getYear ()); System.out.println ("Tonaža =" + truck.getTonnage ()); truck.print ();

Zadnja vrstica, truck.print ();, klici tovornjakje natisni () metoda. Ta metoda najprej pokliče Voziloje natisni () za prikaz znamke, modela in leta tovornjaka; nato odda tonažo tovornjaka. Ta del rezultata je prikazan spodaj:

Znamka: Ford, Model: F150, Leto: 2008 Tonaža: 0,5

Uporabite final, da blokirate preglasitev metode

Občasno boste morda morali prijaviti metodo, ki je zaradi varnosti ali drugega razloga ne bi smeli preglasiti. Lahko uporabite dokončno ključna beseda za ta namen. Če želite preprečiti razveljavitev, preprosto pred glavo glave metode dodajte dokončno, kot v končni niz getMake (). Prevajalnik bo nato sporočil napako, če bo kdo poskušal to metodo preglasiti v podrazredu.

Preobremenitev metode v primerjavi s preglasitvijo

Recimo, da ste zamenjali natisni () v seznamu 7 s spodnjim:

void print (Lastnik niza) {System.out.print ("Owner:" + owner); super.print (); }

Spremenjeno Tovornjak razred ima zdaj dva natisni () metode: prejšnja izrecno deklarirana metoda in metoda, podedovana od Vozilo. The void print (lastnik niza) metoda ne preglasi Voziloje natisni () metoda. Namesto tega preobremenitve to.

Poskus preobremenitve lahko zaznate, namesto da bi preglasili metodo v času prevajanja, tako da pred glavo glave metode podrazreda dodate @Override opomba:

@Override void print (Lastnik niza) {System.out.print ("Lastnik:" + lastnik); super.print (); }

Določanje @Override pove prevajalniku, da podana metoda preglasi drugo metodo. Če bi nekdo poskušal metodo preobremeniti, bi prevajalnik sporočil napako. Brez tega pripisa prevajalnik ne bi poročal o napaki, ker je preobremenitev metode zakonita.

Kdaj uporabiti @Override

Razvijte navado predpiševanja nadrejenih metod pred @Override. Ta navada vam bo veliko prej pomagala odkriti napake pri preobremenitvi.

$config[zx-auto] not found$config[zx-overlay] not found