Java tukee luokan uudelleenkäyttöä perimisen ja sommittelun kautta. Tämä kaksiosainen opetusohjelma opettaa sinulle, miten perintöä käytetään Java-ohjelmissa. Osassa 1 opit käyttämään ulottuu
avainsana johtaa lapsiluokka vanhempien luokasta, käyttää vanhempien luokan rakentajia ja menetelmiä sekä ohittaa menetelmiä. Osassa 2 kiertue java.lang.objekti
, joka on Javan superluokka, josta kaikki muut luokat perivät.
Viimeistele oppimisesi perinnöstä tarkistamalla Java-vinkkini, jossa selitetään, milloin koostumusta ja perintöä käytetään. Opit, miksi sommittelu on tärkeä lisäys perintöön, ja kuinka sitä käytetään suojaamaan Java-ohjelmiesi kapselointiin liittyviltä ongelmilta.
lataa Hanki koodi Lataa lähdekoodi esimerkiksi sovelluksiin tässä opetusohjelmassa. Luonut Jeff Friesen JavaWorldille.Java-perintö: Kaksi esimerkkiä
Perintö on ohjelmointirakenne, jota ohjelmistokehittäjät käyttävät perustamiseen on-suhde luokkien välillä. Perinnön avulla voimme johtaa tarkempia luokkia yleisemmistä luokista. Tarkempi luokka on eräänlainen yleisempi luokka. Esimerkiksi sekkitili on eräänlainen tili, jolla voit tehdä talletuksia ja nostaa. Vastaavasti kuorma-auto on eräänlainen ajoneuvo, jota käytetään suurten tavaroiden vetämiseen.
Perintö voi laskeutua useilla tasoilla, mikä johtaa yhä tarkempiin luokkiin. Esimerkkinä kuvassa 1 esitetään auto ja kuorma-auto perimällä ajoneuvosta; farmari periytyy autosta; ja roska-auto peri kuorma-autoista. Nuolet osoittavat tarkemmista "lapsi" -luokista (alhaalta alaspäin) vähemmän erityisiin "vanhempien" luokkiin (ylempänä).
Jeff FriesenTämä esimerkki kuvaa yksi perintö jossa lapsiluokka perii tilan ja käyttäytymisen yhdestä välittömästä vanhempaluokasta. Verrattuna, moniperintö mahdollistaa lapsiluokan periä tilan ja käyttäytymisen kahdesta tai useammasta välittömästä vanhempaluokasta. Kuvion 2 hierarkia kuvaa useita perintöjä.
Jeff FriesenLuokat kuvataan luokittain. Java tukee yhden perinnön kautta luokan laajennus, jossa yksi luokka perii suoraan käytettävissä olevat kentät ja menetelmät toiselta luokalta laajentamalla kyseistä luokkaa. Java ei kuitenkaan tue useita perintöjä luokan laajennuksen kautta.
Kun tarkastelet perintöhierarkiaa, voit helposti tunnistaa useita perintöjä timanttikuvion avulla. Kuvassa 2 on esitetty tämä malli ajoneuvon, maakulkuneuvon, vesikulkuneuvon ja ilmatyynyaluksen yhteydessä.
Laajentaa avainsanan
Java tukee luokan laajennusta ulottuu
avainsana. Läsnä ollessa ulottuu
määrittää vanhempien ja lasten välisen suhteen kahden luokan välillä. Alla käytän ulottuu
luoda suhde luokkien välillä Ajoneuvo
ja Auto
ja sitten välillä Tili
ja Säästötili
:
Listaus 1. The ulottuu
avainsana määrittää vanhemman ja lapsen välisen suhteen
luokka Ajoneuvo {// jäsenilmoitukset} luokka Auto laajentaa ajoneuvoa {// peri esteettömät jäsenet ajoneuvosta // anna omat jäsenilmoitukset} luokka Tili {// jäsenilmoitukset} luokka SäästötTili laajentaa tiliä {// peri käytettävissä olevat jäsenet tililtä // tarjoa omien jäsenten ilmoitukset}
ulottuu
avainsana määritetään luokan nimen jälkeen ja ennen toista luokan nimeä. Luokan nimi aiemmin ulottuu
tunnistaa lapsen ja luokan nimen jälkeen ulottuu
tunnistaa vanhemman. On mahdotonta määrittää useita luokkien nimiä jälkeen ulottuu
koska Java ei tue luokkaperusteista useita perintöjä.
Nämä esimerkit kodifioivat is-a-suhteet: Auto
on erikoistunut Ajoneuvo
ja Säästötili
on erikoistunut Tili
. Ajoneuvo
ja Tili
tunnetaan nimellä perusluokkia, vanhempien luokattai superluokkia. Auto
ja Säästötili
tunnetaan nimellä johdetut luokat, lasten luokattai alaluokat.
Viimeiset luokat
Voit julistaa luokan, jota ei pidä laajentaa; esimerkiksi turvallisuussyistä. Javassa käytämme lopullinen
avainsana estää joidenkin luokkien jatkamisen. Yksinkertaisesti lisää etuliitteeseen luokan otsikko lopullinen
, kuten viimeisen luokan salasana
. Tämän ilmoituksen perusteella kääntäjä ilmoittaa virheestä, jos joku yrittää laajentaa Salasana
.
Lapsiluokituksessa peritään käytettävissä olevat kentät ja menetelmät vanhemmilta luokilta ja muilta esi-isiltä. He eivät koskaan peri rakentajia. Sen sijaan lapsiluokat ilmoittavat omat rakentajansa. Lisäksi he voivat ilmoittaa omat kentänsä ja menetelmänsä erottaakseen heidät vanhemmistaan. Harkitse listaa 2.
Listaus 2. An Tili
vanhempien luokka
luokan tili {yksityinen merkkijono nimi; yksityinen pitkä summa; Tili (merkkijonon nimi, pitkä summa) {this.name = nimi; setAmount (määrä); } mitätöity talletus (pitkä summa) {tämä.summa + = summa; } Merkkijono getName () {return name; } pitkä getAmount () {palautussumma; } void setAmount (pitkä summa) {this.amount = summa; }}
Listaus 2 kuvaa yleistä pankkitililuokkaa, jolla on nimi ja alkusumma, jotka molemmat on määritetty konstruktorissa. Lisäksi se antaa käyttäjien tehdä talletuksia. (Voit tehdä nostoja tallettamalla negatiivisia rahamääriä, mutta jätämme tämän mahdollisuuden huomiotta.) Huomaa, että tilin nimi on määritettävä tilin luomisen yhteydessä.
Valuutan arvojen esittäminen
pennien määrä. Haluat ehkä käyttää a kaksinkertainen
tai a kellua
rahallisten arvojen tallentamiseen, mutta se voi johtaa epätarkkuuksiin. Harkitse parempaa ratkaisua BigDecimal
, joka on osa Java-standardikurssikirjastoa.
Luettelossa 3 esitetään a Säästötili
lapsiluokka, joka laajentaa sen Tili
vanhempien luokka.
Listaus 3. A Säästötili
lapsiluokka laajentaa Tili
vanhempien luokka
class SavingsAccount laajentaa tiliä {SavingsAccount (pitkä summa) {super ("säästöt", summa); }}
Säästötili
luokka on triviaali, koska sen ei tarvitse ilmoittaa muita kenttiä tai menetelmiä. Se kuitenkin julistaa konstruktorin, joka alustaa kentät sen kentässä Tili
superluokka. Alustus tapahtuu, kun Tili
konstruktoria kutsutaan Java: n kautta super
avainsana, jota seuraa sulutettu argumenttiluettelo.
Milloin ja mihin soittaa super ()
Aivan kuten Tämä()
täytyy olla konstruktorin ensimmäinen elementti, joka kutsuu toisen saman luokan rakentajan, super ()
on oltava ensimmäinen elementti konstruktorissa, joka kutsuu konstruktorin yläluokkaansa. Jos rikot tätä sääntöä, kääntäjä ilmoittaa virheestä. Kääntäjä ilmoittaa myös virheestä, jos se havaitsee a super ()
kutsu menetelmä; vain koskaan soittaa super ()
konstruktorissa.
Listaus 4 jatkuu edelleen Tili
kanssa Tarkistetaan tili
luokassa.
Listaus 4. A Tarkistetaan tili
lapsiluokka laajentaa Tili
vanhempien luokka
class CheckingAccount laajentaa tiliä {CheckingAccount (pitkä summa) {super ("check", summa); } mitätön kotiutus (pitkä summa) {setAmount (getAmount () - summa); }}
Tarkistetaan tili
on hieman merkittävämpi kuin Säästötili
koska se ilmoittaa a peruuttaa()
menetelmä. Huomaa tämän menetelmän kutsut setAmount ()
ja getAmount ()
, joka Tarkistetaan tili
perii Tili
. Et voi käyttää suoraan määrä
kenttä Tili
koska tämä kenttä on ilmoitettu yksityinen
(katso luettelo 2).
super () ja argumenttittomat konstruktorit
Jos super ()
ei ole määritelty alaluokan rakennuttajassa, ja jos yliluokka ei ilmoita a ei väitettä
konstruktori, kääntäjä ilmoittaa virheestä. Tämä johtuu siitä, että alaluokan rakentajan on kutsuttava a ei väitettä
superluokan rakentaja kun super ()
ei ole läsnä.
Luokkahierarkiaesimerkki
Olen luonut AccountDemo
sovellusluokka, jonka avulla voit kokeilla Tili
luokan hierarkia. Katsokaa ensin AccountDemo
lähdekoodi.
Listaus 5. AccountDemo
osoittaa tililuokan hierarkian
class AccountDemo {public static void main (Merkkijono [] argumentit) {SavingsAccount sa = new SavingsAccount (10000); System.out.println ("tilin nimi:" + sa.getName ()); System.out.println ("alkumäärä:" + sa.getAmount ()); sa. talletus (5000); System.out.println ("uusi summa talletuksen jälkeen:" + sa.getAmount ()); CheckingAccount ca = uusi CheckingAccount (20000); System.out.println ("tilin nimi:" + ca.getName ()); System.out.println ("alkumäärä:" + ca.getAmount ()); noin talletus (6000); System.out.println ("uusi summa talletuksen jälkeen:" + ca.getAmount ()); noin vetäytyi (3000); System.out.println ("uusi summa noston jälkeen:" + ca.getAmount ()); }}
main ()
Listauksen 5 menetelmä osoittaa ensin Säästötili
sitten Tarkistetaan tili
. Oletetaan Account.java
, SavingsAccount.java
, CheckingAccount.java
ja AccountDemo.java
lähdetiedostot ovat samassa hakemistossa, koota kaikki nämä lähdetiedostot suorittamalla jompikumpi seuraavista komennoista:
javac AccountDemo.java javac * .java
Suorita sovellus suorittamalla seuraava komento:
java AccountDemo
Ota huomioon seuraava tulos:
tilin nimi: säästöjen alkumäärä: 10000 uusi summa talletuksen jälkeen: 15000 tilin nimi: tarkistetaan alkusumma: 20000 uusi summa talletuksen jälkeen: 26000 uusi summa noston jälkeen: 23000
Menetelmän ohittaminen (ja menetelmän ylikuormitus)
Alaluokka voi ohittaa (korvaa) peritty menetelmä siten, että sen sijaan kutsutaan menetelmän alaluokan versiota. Korvaavan menetelmän on määritettävä sama nimi, parametriluettelo ja palautustyyppi kuin ohitettava menetelmä. Osoittaakseni olen ilmoittanut a Tulosta()
menetelmä Ajoneuvo
luokka alla.
Luettelo 6. Ilmoitus a Tulosta()
menetelmä ohitetaan
luokka Ajoneuvo {yksityinen merkkijono; yksityinen merkkijono malli; yksityinen kansainvälinen vuosi; Ajoneuvo (merkkijono, kielimalli, vuosimalli) {this.make = merkki; tämä malli = malli; tämä.vuosi = vuosi; } Merkkijono getMake () {return make; } String getModel () {palautusmalli; } int getYear () {paluuvuosi; } void print () {System.out.println ("Merkki:" + merkki + ", Malli:" + malli + ", Vuosi:" + vuosi); }}
Seuraavaksi ohitan Tulosta()
että Kuorma-auto
luokassa.
Listaus 7. Korvaava Tulosta()
jonkin sisällä Kuorma-auto
alaluokka
luokka kuorma-auto jatkuu Ajoneuvo {yksityinen kaksinkertainen vetoisuus; Kuorma-auto (merkkijono, jousimalli, sisävuosi, kaksinkertainen tonnimäärä) {super (merkki, malli, vuosi); this.tonnage = tonnimäärä; } double getTonnage () {paluuvetoisuus; } void print () {super.print (); System.out.println ("Määrä:" + tonnimäärä); }}
Kuorma-auto
on Tulosta()
menetelmällä on sama nimi, palautustyyppi ja parametriluettelo kuin Ajoneuvo
on Tulosta()
menetelmä. Huomaa myös se Kuorma-auto
on Tulosta()
menetelmä ensin kutsuu Ajoneuvo
on Tulosta()
menetelmä etuliitteellä super.
menetelmän nimeen. Usein on hyvä suorittaa ensin yliluokan logiikka ja sitten aliluokan logiikka.
Yliluokan menetelmien kutsuminen alaluokamenetelmistä
Soittaaksesi yliluokan menetelmän ohittavasta aliluokan menetelmästä, lisää menetelmän nimi varattuun sanaan super
ja jäsenen käyttöoperaattori. Muuten pääset rekursiivisesti kutsumaan alaluokan ohittavaa menetelmää. Joissakin tapauksissa alaluokka peittää ei-yksityinen
superluokan kentät ilmoittamalla samannimiset kentät. Voit käyttää super
ja jäsenen käyttöoperaattorin pääsy muihin kuinyksityinen
superluokan kentät.
Tämän esimerkin täydentämiseksi olen ote a AjoneuvoDemo
luokan main ()
menetelmä:
Kuorma-auto = uusi kuorma-auto ("Ford", "F150", 2008, 0,5); System.out.println ("Merkki =" + kuorma-auto.getMake ()); System.out.println ("Malli =" + kuorma-auto.getModel ()); System.out.println ("Vuosi =" + kuorma-auto.GetYear ()); System.out.println ("Tonnage =" + kuorma-auto.getTonnage ()); truck.print ();
Viimeinen rivi kuorma-auto.tulos ();
, puhelut kuorma-auto
on Tulosta()
menetelmä. Tämä menetelmä soittaa ensin Ajoneuvo
on Tulosta()
antaa kuorma-auton merkki, malli ja vuosi; sitten se antaa kuorma-auton vetoisuuden. Tämä tuotoksen osa on esitetty alla:
Merkki: Ford, Malli: F150, Vuosi: 2008 Massa: 0.5
Estä menetelmän ohitus käyttämällä lopullista
Joskus sinun on ehkä ilmoitettava menetelmä, jota ei pidä ohittaa turvallisuuden tai muun syyn vuoksi. Voit käyttää lopullinen
avainsana tähän tarkoitukseen. Voit estää ohittamisen yksinkertaisesti etuliittämällä metodin otsikon lopullinen
, kuten viimeinen merkkijono getMake ()
. Kääntäjä ilmoittaa sitten virheestä, jos joku yrittää ohittaa tämän menetelmän alaluokassa.
Menetelmän ylikuormitus vs. ohittaminen
Oletetaan, että olet vaihtanut Tulosta()
Listaus 7 -menetelmällä alla olevan menetelmän kanssa:
void print (merkkijonon omistaja) {System.out.print ("Omistaja:" + omistaja); super.tulos (); }
Muokattu Kuorma-auto
luokassa on nyt kaksi Tulosta()
Methods: edellinen nimenomaisesti ilmoitettu menetelmä ja menetelmä, joka on peritty Ajoneuvo
. void print (merkkijonon omistaja)
menetelmä ei korvaa Ajoneuvo
on Tulosta()
menetelmä. Sen sijaan se ylikuormitukset se.
Voit havaita ylikuormitusyrityksen menetelmän korvaamisen sijaan kääntämisajankohtana etuliittämällä aliluokan metodin otsikon @Ohittaa
merkintä:
@Override void print (Merkkijonon omistaja) {System.out.print ("Omistaja:" + omistaja); super.tulos (); }
Määritetään @Ohittaa
kertoo kääntäjälle, että annettu menetelmä ohittaa toisen menetelmän. Jos joku yritti ylikuormittaa menetelmää sen sijaan, kääntäjä ilmoitti virheestä. Ilman tätä merkintää kääntäjä ei ilmoita virheestä, koska menetelmän ylikuormitus on laillista.
Milloin @Overrideä käytetään
Kehitä tapana etuliittää etusijalla olevat menetelmät @Ohittaa
. Tämä tapa auttaa havaitsemaan ylikuormitusvirheet paljon nopeammin.