Programavimas

Paveldėjimas „Java“, 1 dalis: Išplečiamas raktinis žodis

„Java“ palaiko klasės pakartotinį naudojimą paveldėjimo ir sudėties būdu. Ši dviejų dalių mokymo programa išmokys jus naudoti paveldėjimą savo „Java“ programose. 1 dalyje sužinosite, kaip naudoti tęsiasi raktinį žodį, kad gautumėte vaikų klasę iš tėvų klasės, pasikvieskite tėvų klasės konstruktorius ir metodus bei ignoruosite metodus. 2 dalyje apžiūrėsite java.lang.Object, kuris yra „Java“ superklasė, iš kurios paveldi visos kitos klasės.

Norėdami baigti mokymąsi apie paveldėjimą, būtinai peržiūrėkite mano „Java“ patarimą, kuriame paaiškinta, kada naudoti kompoziciją ir paveldėjimą. Sužinosite, kodėl kompozicija yra svarbus paveldėjimo papildymas ir kaip ją naudoti, kad apsisaugotumėte nuo problemų, susijusių su jūsų Java programų inkapsuliacija.

atsisiųsti Gauti kodą Atsisiųskite šaltinį, pvz., programas, šioje pamokoje. Sukūrė Jeffas Friesenas, skirtas „JavaWorld“.

Java paveldėjimas: du pavyzdžiai

Paveldėjimas yra programavimo konstrukcija, kurią sukuria programinės įrangos kūrėjai yra-santykiai tarp kategorijų. Paveldėjimas leidžia mums išgauti konkretesnes kategorijas iš bendresnių. Konkrečiau kategorija yra tam tikros rūšies generiškesnė kategorija. Pavyzdžiui, atsiskaitomoji sąskaita yra tam tikra sąskaita, kurioje galite atlikti indėlius ir išsigryninti. Panašiai sunkvežimis yra tam tikra transporto priemonė, naudojama gabenti didelius daiktus.

Paveldėjimas gali nusileisti keliais lygmenimis, o tai lemia vis specifines kategorijas. Pavyzdžiui, 1 paveiksle parodytas automobilio ir sunkvežimio paveldėjimas iš transporto priemonės; universalas, paveldimas iš automobilio; ir šiukšliavežis, paveldėtas iš sunkvežimio. Rodyklės nurodo iš konkretesnių „vaikų“ kategorijų (žemyn žemyn) į mažiau specifines „tėvų“ kategorijas (aukštesnės).

Jeffas Friesenas

Šis pavyzdys iliustruoja vienas paveldėjimas kurioje vaiko kategorija paveldi būseną ir elgesį iš vienos tiesioginių tėvų kategorijos. Priešingai, daugkartinis paveldėjimas leidžia vaiko kategorijai paveldėti būseną ir elgesį iš dviejų ar daugiau tiesioginių tėvų kategorijų. 2 paveiksle esanti hierarchija iliustruoja daugybinį paveldėjimą.

Jeffas Friesenas

Kategorijos apibūdinamos pagal klases. „Java“ palaiko vieną paveldėjimą klasės pratęsimas, kurioje viena klasė tiesiogiai paveldi prieinamus laukus ir metodus iš kitos klasės, pratęsdama tą klasę. Vis dėlto „Java“ nepalaiko kelių paveldėjimų per klasės pratęsimą.

Peržiūrėdami paveldėjimo hierarchiją, galite lengvai aptikti kelis paveldėjimus pagal deimantų modelį. 2 paveiksle pavaizduotas šis modelis transporto priemonės, sausumos transporto priemonės, vandens transporto priemonės ir orlaivio kontekste.

Praplečiamas raktinis žodis

„Java“ palaiko klasės pratęsimą per tęsiasi raktinis žodis. Kai yra, tęsiasi nurodo tėvų ir vaikų santykius tarp dviejų klasių. Žemiau aš naudoju tęsiasi užmegzti santykį tarp klasių Transporto priemonė ir Automobilisir tada tarp Sąskaita ir Taupomoji sąskaita:

Sąrašas 1. The tęsiasi raktinis žodis nurodo tėvų ir vaikų santykius

klasė Transporto priemonė {// narių deklaracijos} klasė Automobilis pratęsia transporto priemonę {// paveldi prieinamus narius iš Transporto priemonės // pateik savo narių deklaracijas} klasė Sąskaita {// narių deklaracijos} klasė Taupomoji sąskaita pratęsia sąskaitą {// paveldi prieinamus narius iš paskyros // pateikti savo narių deklaracijos}

tęsiasi raktinis žodis nurodomas po klasės pavadinimo ir prieš kitą klasės pavadinimą. Klasės pavadinimas anksčiau tęsiasi identifikuoja vaiką ir klasės pavadinimą po tęsiasi identifikuoja tėvą. Po to neįmanoma nurodyti kelių klasių pavadinimų tęsiasi nes „Java“ nepalaiko daugelio klasių paveldėjimo.

Šie pavyzdžiai užkoduoja ryšius: Automobilisyra specializuota Transporto priemonė ir Taupomoji sąskaitayra specializuota Sąskaita. Transporto priemonė ir Sąskaita yra žinomi kaip bazinės klasės, tėvų klasėsarba superklasės. Automobilis ir Taupomoji sąskaita yra žinomi kaip išvestinės klasės, vaikų klasėsarba poklasiai.

Baigiamosios klasės

Galite paskelbti klasę, kurios nereikėtų pratęsti; pavyzdžiui, saugumo sumetimais. „Java“ mes naudojame galutinis raktinį žodį, kad būtų išvengta kai kurių klasių pratęsimo. Paprasčiausiai pridėkite klasės antraštę galutinis, kaip ir paskutinės klasės slaptažodis. Atsižvelgdamas į šią deklaraciją, kompiliatorius praneš apie klaidą, jei kas nors bandys išplėsti Slaptažodis.

Vaikų klasės paveldimus laukus ir metodus paveldi iš savo tėvų klasių ir kitų protėvių. Tačiau jie niekada nepaveldi konstruktorių. Vietoj to, vaikų klasės deklaruoja savo konstruktorius. Be to, jie gali deklaruoti savo sritis ir metodus, kaip juos atskirti nuo tėvų. Apsvarstykite 2 sąrašą.

2. sąrašas Sąskaita tėvų klasė

klasės sąskaita {private String name; privati ​​ilga suma; Sąskaita (eilutės pavadinimas, ilga suma) {this.name = vardas; setAmount (suma); } negaliojantis indėlis (ilga suma) {this.suma + = suma; } String getName () {grąžinimo vardas; } long getAmount () {grąžinimo suma; } void setAmount (ilga suma) {this.suma = suma; }}

2 sąraše aprašoma bendroji banko sąskaitos klasė, turinti pavadinimą ir pradinę sumą, kurios abi nustatytos konstruktoriuje. Be to, tai leidžia vartotojams atlikti indėlius. (Galite išsigryninti įnešdami neigiamas pinigų sumas, bet mes nepaisysime šios galimybės.) Atminkite, kad sąskaitos pavadinimas turi būti nustatytas sukūrus sąskaitą.

Reprezentuojančios valiutos vertės

centų skaičius. Galbūt norėtumėte naudoti a dvigubai arba a plūdė saugoti pinigines vertes, tačiau tai gali sukelti netikslumų. Norėdami apsvarstyti geresnį sprendimą, apsvarstykite Didelis dešimtainis, kuri yra „Java“ standartinės klasės bibliotekos dalis.

3 sąraše pateikiami a Taupomoji sąskaita vaikų klasė, kuri pratęsia savo Sąskaita tėvų klasė.

Sąrašas 3. A Taupomoji sąskaita vaikų klasė pratęsia savo Sąskaita tėvų klasė

klasė Taupomoji sąskaita pratęsia Sąskaitą {Taupomoji sąskaita (ilga suma) {super ("taupymas", suma); }}

Taupomoji sąskaita klasė yra nereikšminga, nes jai nereikia deklaruoti papildomų laukų ar metodų. Tačiau jis paskelbia konstruktorių, kuris inicijuoja jo laukus Sąskaita superklasė. Inicijavimas įvyksta, kai Sąskaitakonstruktorius vadinamas Java super raktinis žodis, po kurio pateikiamas skliaustuose pateiktas argumentų sąrašas.

Kada ir kur skambinti super ()

Lygiai taip tai () turi būti pirmasis konstruktoriaus elementas, iškviečiantis kitą tos pačios klasės konstruktorių, super () turi būti pirmasis konstruktoriaus elementas, kuris iškviečia konstruktorių savo superklase. Jei pažeisite šią taisyklę, kompiliatorius praneš apie klaidą. Kompiliatorius taip pat praneš apie klaidą, jei aptiks a super () iškviesti metodą; tik kada skambinti super () konstruktoriuje.

4 sąrašas dar tęsiasi Sąskaita su „CheckingAccount“ klasė.

Sąrašas 4. A „CheckingAccount“ vaikų klasė pratęsia savo Sąskaita tėvų klasė

klasė „CheckingAccount“ pratęsia sąskaitą {CheckingAccount (ilga suma) {super ("tikrinimas", suma); } negaliojantis atsiimti (ilga suma) {setAmount (getAmount () - suma); }}

„CheckingAccount“ yra šiek tiek reikšmingesnis nei Taupomoji sąskaita nes deklaruoja a atsiimti () metodas. Atkreipkite dėmesį į šio metodo raginimus setAmount () ir getAmount (), kuris „CheckingAccount“ paveldi iš Sąskaita. Negalite tiesiogiai pasiekti suma laukas Sąskaita nes šis laukas yra deklaruotas privatus (žr. 2 sąrašą).

super () ir be argumentų konstruktorius

Jei super () nėra nurodytas poklasio konstruktoriuje, o jei superklasė nedeklaruoja a be argumentų konstruktorius, tada kompiliatorius praneš apie klaidą. Taip yra todėl, kad poklasio konstruktorius turi paskambinti a be argumentų superklasės konstruktorius, kai super () nėra.

Klasių hierarchijos pavyzdys

Aš sukūriau „AccountDemo“ programos klasė, leidžianti išbandyti Sąskaita klasės hierarchija. Pirmiausia pažvelk į „AccountDemo“šaltinio kodas.

5 sąrašas. „AccountDemo“ parodo sąskaitų klasės hierarchiją

class AccountDemo {public static void main (String [] args) {Taupomoji sąskaita sa = nauja Taupomoji sąskaita (10000); System.out.println ("paskyros pavadinimas:" + sa.getName ()); System.out.println ("pradinė suma:" + sa.getAmount ()); sa.depositas (5000); System.out.println ("nauja suma po indėlio:" + sa.getAmount ()); „CheckingAccount ca“ = nauja „CheckingAccount“ (20000); System.out.println ("paskyros pavadinimas:" + ca.getName ()); System.out.println ("pradinė suma:" + ca.getAmount ()); maždaug indėlis (6000); System.out.println ("nauja suma po indėlio:" + ca.getAmount ()); maždaug atsiimti (3000); System.out.println ("nauja suma po atsiėmimo:" + ca.getAmount ()); }}

pagrindinis () metodas 5 sąraše pirmiausia parodo Taupomoji sąskaitatada „CheckingAccount“. Darant prielaidą Account.java, Taupomoji sąskaita.java, CheckingAccount.javair AccountDemo.java šaltinio failai yra tame pačiame kataloge, atlikite bet kurią iš šių komandų, kad sukompiluotumėte visus šiuos šaltinio failus:

javac AccountDemo.java javac * .java

Norėdami paleisti programą, vykdykite šią komandą:

„java AccountDemo“

Turėtumėte stebėti šį rezultatą:

sąskaitos pavadinimas: taupymo pradinė suma: 10000 nauja suma po indėlio: 15000 sąskaitos pavadinimas: tikrinant pradinę sumą: 20000 nauja suma po indėlio: 26000 nauja suma po atsiėmimo: 23000

Metodo viršijimas (ir metodo perkrova)

Poklasis gali nepaisyti (pakeisti) paveldėtą metodą, kad vietoj jo būtų iškviesta poklasio versija. Nepaisomas metodas turi nurodyti tą patį pavadinimą, parametrų sąrašą ir grąžinimo tipą, kaip ir metodas, kurio nepaisoma. Norėdamas parodyti, aš paskelbiau a spausdinti () metodas Transporto priemonė klasė žemiau.

Sąrašas 6. Deklaravimas a spausdinti () metodas turi būti nepaisomas

klasės transporto priemonė {privati ​​styginių markė; privati ​​styginių modelis; privatus int metai; Transporto priemonė (styginių markė, styginių modelis, metų metai) {this.make = markė; tai.modelis = modelis; tai.metai = metai; } String getMake () {return make; } String getModel () {grąžinimo modelis; } int getYear () {grąžinimo metai; } void print () {System.out.println ("Gamintojas:" + padarykite + ", Modelis:" + modelis + ", Metai:" + metai); }}

Toliau aš nepaisau spausdinti () viduje konors Sunkvežimis klasė.

Sąrašas 7. Nepaisoma spausdinti () a Sunkvežimis poklasis

klasės sunkvežimis prailgina transporto priemonę {privatus dvigubas tonažas; Sunkvežimis (styginių markė, styginių modelis, tarptautiniai metai, dvigubas tonažas) {super (markė, modelis, metai); this.tonnage = tonažas; } double getTonnage () {grąžinimo tonažas; } void print () {super.print (); System.out.println ("Tonažas:" + tonažas); }}

Sunkvežimis's spausdinti () metodas turi tą patį pavadinimą, grąžinimo tipą ir parametrų sąrašą kaip Transporto priemonė's spausdinti () metodas. Atkreipkite dėmesį ir į tai Sunkvežimis's spausdinti () metodas pirmiausia skambina Transporto priemonė's spausdinti () metodas priešdėliais super. prie metodo pavadinimo. Dažnai yra gera idėja pirmiausia įvykdyti superklasės logiką, o paskui - poklasio logiką.

Supaklasės metodų iškvietimas iš poklasio metodų

Norėdami iškviesti superklasės metodą iš svarbesnio poklasio metodo, prieš metodo pavadinimą įrašykite rezervuotą žodį super ir nario prieigos operatorius. Priešingu atveju jūs rekursyviai iškviesite poklasio svarbesnįjį metodą. Kai kuriais atvejais poklasis užmaskuos neprivatus superklasės laukų, deklaruodami to paties pavadinimo laukus. Tu gali naudoti super nariams ir prieigos nariams prieigai prie neprivatus superklasės laukai.

Norėdami užbaigti šį pavyzdį, ištraukiau a „VehicleDemo“ klasės pagrindinis () metodas:

Sunkvežimis = naujas sunkvežimis („Ford“, „F150“, 2008, 0,5); System.out.println ("Make =" + truck.getMake ()); System.out.println ("Model =" + truck.getModel ()); System.out.println ("Metai =" + sunkvežimis.getYear ()); System.out.println ("Tonnage =" + sunkvežimis.getTonnage ()); sunkvežimis.spauda ();

Paskutinė eilutė sunkvežimis.spauda ();, skambučiai sunkvežimis's spausdinti () metodas. Šis metodas pirmiausia skambina Transporto priemonė's spausdinti () pateikti sunkvežimio markę, modelį ir metus; tada jis pateikia sunkvežimio tonažą. Ši išvesties dalis parodyta žemiau:

Markė: Ford, Modelis: F150, Metai: 2008 Tonažas: 0.5

Norėdami užblokuoti metodo nepaisymą, naudokite final

Kartais dėl saugumo ar kitų priežasčių gali tekti deklaruoti metodą, kurio nereikėtų nepaisyti. Galite naudoti galutinis raktinis žodis šiam tikslui. Norėdami išvengti nepaisymo, paprasčiausiai prieš metodo antraštę įrašykite galutinis, kaip ir paskutinė eilutė „getMake“ (). Tada kompiliatorius praneš apie klaidą, jei kas nors bandys nepaisyti šio metodo poklasyje.

Metodo perkrova ir nepaisoma

Tarkime, kad pakeitėte spausdinti () metodas 7 sąraše su vienu iš toliau pateiktų būdų:

void print (eilutės savininkas) {System.out.print ("Savininkas:" + savininkas); super.spaudas (); }

Modifikuotas Sunkvežimis klasėje dabar yra du spausdinti () metodai: prieš tai aiškiai deklaruotas metodas ir iš jo paveldėtas metodas Transporto priemonė. negaliojantis spausdinimas (eilutės savininkas) metodas nepaiso Transporto priemonė's spausdinti () metodas. Vietoj to perkrovos tai.

Bandymą perkrauti, užuot nepaisius metodo kompiliavimo metu, galite aptikti priešklasei metodo antraštę pridėdami @ Nepaisyti anotacija:

@ Nepaisyti negaliojančio spausdinimo (eilutės savininkas) {System.out.print ("Savininkas:" + savininkas); super.spaudas (); }

Nurodant @ Nepaisyti kompiliatoriui sako, kad nurodytas metodas nepaiso kito metodo. Jei kas nors bandė perkrauti metodą, kompiliatorius praneša apie klaidą. Be šios anotacijos kompiliatorius nepraneša apie klaidą, nes metodo perkrovimas yra teisėtas.

Kada naudoti „@Override“

Išsiugdykite įprotį prefiksuoti svarbiausius metodus @ Nepaisyti. Šis įprotis padės daug greičiau aptikti perkrovos klaidas.