Luokkaperintö on yhden luokan tapa laajentaa toista luokkaa.
joten voimme luoda uusia toimintoja olemassa olevan päälle.
Se ”ulottuu” avainsanan
sanotaan, että meillä on luokan Animal
:
Tässä on, miten voimme edustaa animal
objekti ja Animal
luokan graafisesti:
…Ja haluaisimme luoda toinen class Rabbit
.,
Kuten kanit ovat eläimiä, Rabbit
luokka olisi perustuttava Animal
, on pääsy eläinten menetelmiä, niin, että kanit voivat tehdä mitä ”yleinen” eläimet voivat tehdä.
toisen luokan pidentämisen syntaksi on: class Child extends Parent
.
luodaan class Rabbit
, joka perii Animal
:
Kohde Rabbit
class on käyttää sekä Rabbit
menetelmiä, kuten rabbit.hide()
, ja myös Animal
menetelmiä, kuten rabbit.run()
.,
Sisäisesti extends
avainsana toimii käyttämällä vanhoja hyviä prototyyppi mekaniikka. Se asettaa Rabbit.prototype.]
ja Animal.prototype
. Joten, jos menetelmä ei löydy Rabbit.prototype
, JavaScript vie sen Animal.prototype
.,
esimerkiksi, löytää rabbit.run
menetelmä, moottorin tarkastukset (bottom-up kuva):
Kuten muistamme luvusta prototyyppejä, JavaScript itse käyttää prototypal perintö sisäänrakennettu esineitä. E. g. Date.prototype.]
on Object.prototype
. Siksi päivämäärillä on pääsy yleisiin objektimenetelmiin.,
extends
Luokka-syntaksin avulla voidaan määrittää, ei vain luokassa, mutta mikä tahansa lauseke, kun extends
.
esimerkiksi funktiokutsu, joka tuottaa vanhemman luokan:
function f(phrase) { return class { sayHi() { alert(phrase); } };}class User extends f("Hello") {}new User().sayHi(); // Hello
Täältä class User
perii tulos f("Hello")
.,
se voi olla hyödyllistä edistyneille ohjelmointikaavoille, kun käytämme funktioita luokkien luomiseen monista ehdoista riippuen ja voimme periä ne.
Ensisijainen menetelmä
– Nyt mennään eteenpäin ja ohittaa menetelmä. Oletuksena, kaikki menetelmät, joita ei ole määritelty class Rabbit
otetaan suoraan ”kuin on” class Animal
.,
Mutta jos me määrittää oman menetelmä Rabbit
, esimerkiksi stop()
sitten sitä käytetään sen sijaan:
class Rabbit extends Animal { stop() { // ...now this will be used for rabbit.stop() // instead of stop() from class Animal }}
Yleensä emme halua täysin korvata vanhempi menetelmä, vaan pikemminkin rakentaa sen päälle nipistää tai laajentaa sen toiminnallisuutta. Teemme jotain menetelmässämme, mutta soitamme vanhemman menetelmään ennen/jälkeen sen tai prosessissa.
luokissa on"super"
avainsana sille.
-
super.method(...)
soittaa vanhempi menetelmä., -
super(...)
soittaa vanhemman rakentaja (sisällä meidän rakentaja vain).
esimerkiksi, anna meidän kani autohide kun lopetti:
Nyt Rabbit
on stop
menetelmä, joka vaatii vanhemman super.stop()
prosessissa.
Ensisijainen rakentaja
rakentajien Kanssa se saa hieman hankala.
Asti Rabbit
ei ollut oma constructor
.,
Mukaan erittely, jos luokka ulottuu toisen luokan ja ei ole constructor
, niin seuraavat ”tyhjä” constructor
syntyy:
class Rabbit extends Animal { // generated for extending classes without own constructors constructor(...args) { super(...args); }}
Kuten näemme, se pohjimmiltaan pyytää vanhemman constructor
kulkee se kaikki argumentit. Niin käy, Jos emme kirjoita omaa rakentajaa.
nyt lisätään custom constructor Rabbit
. Se täsmentää earLength
lisäksi name
:
Hups!, Meillä on virhe. Nyt emme voi luoda kaneja. Mikä meni vikaan?
lyhyt vastaus on:
- Konstruktoreja perii luokat on call
super(...)
, ja (!) tee se, ennen kuin käytätthis
.
… mutta miksi? Mitä täällä tapahtuu? Vaatimus vaikuttaa todella oudolta.
tietysti on selitys. Mennään yksityiskohtiin, niin ymmärrät, mitä on tekeillä.
JavaScript, on ero rakentaja toiminto on periä luokka (ns. ”johdettu rakentaja”) ja muita toimintoja., Johdettu konstruktori on erityinen sisäinen ominaisuus ]:"derived"
. Se on erityinen sisäinen merkki.
kyseinen etiketti vaikuttaa sen käyttäytymiseennew
.
- Kun normaali toiminto on toteutettu
new
, se luo tyhjän objektin ja määrittää senthis
. - mutta kun johdettu konstruktor juoksee, se ei tee näin. Se odottaa vanhemman rakentajan tekevän tämän työn.,
Joten johdettu rakentajan on vaadittava super
voidakseen toteuttaa sen vanhemman (base) rakentaja, muuten esine this
ei voida luoda. Ja saamme virheen.
Esimerkiksi Rabbit
rakentajan tekemään työtä, se tarvitsee soittaa super()
ennen this
, kuten tässä:
Ensisijainen luokan kentät: hankala huomata
Tämän huomaa, olettaa, että sinulla on tietty kokemus luokkaa, ehkä muita ohjelmointikieliä.,
se antaa paremman käsityksen kielestä ja selittää myös käyttäytymisen, joka saattaa olla vikojen lähde (mutta ei kovin usein).
Jos sinun on vaikea ymmärtää, jatka vain, jatka lukemista, sitten palata siihen myöhemmin.
voimme ohittaa menetelmien lisäksi luokkakenttiä.
Vaikka on hankala käyttäytyminen, kun me käyttää ohittaa kentän vanhemman rakentaja, aivan erilainen kuin useimmat muut ohjelmointikieliä.,
Mieti tätä esimerkkiä:
Tässä, luokka Rabbit
ulottuu Animal
ja ohitukset name
kenttä, jolla on oma arvo.
ei ole oma rakentajan Rabbit
, niin Animal
rakentajan on nimeltään.
Mikä on mielenkiintoista on, että molemmissa tapauksissa: new Animal()
ja new Rabbit()
, alert
linja (*)
osoittaa animal
.,
eli emokonstruktori käyttää aina omaa kenttäarvoaan, ei ylimitoitettua.
mikä siinä on outoa?
Jos se ei ole vielä selvää, vertaile menetelmiä.
Tässä on sama koodi, mutta sen sijaan this.name
kenttä kutsumme this.showName()
menetelmä:
huom: nyt lähtö on erilainen.
ja sitä luonnollisesti odotamme. Kun emokonstruktoria kutsutaan johdetussa luokassa, se käyttää ylirasitettua menetelmää.
… mutta luokkakentillä se ei ole niin. Kuten sanottu, vanhempi rakentaja käyttää aina emokenttää.,
miksi ero on olemassa?
hyvin, syy on kentän alustusjärjestyksessä. Luokan kenttä alustetaan:
- Ennen kuin rakentaja perustaa luokan (joka ei ulotu mitään),
- Heti
super()
varten johdettu luokka.
meidän tapauksessamme on johdettu luokka. Siinä ei ole constructor()
. Kuten sanoi aiemmin, että on sama, kuin jos siellä oli tyhjä konstruktori vain super(...args)
.,
, new Rabbit()
puhelut super()
siten suorittamalla vanhemman rakentaja, ja (per sääntö johdettu luokat) vasta sen jälkeen sen luokan kentät alustetaan. Tuolloin vanhemman rakentaja toteuttamista, ei ole Rabbit
luokan kentät vielä, siksi Animal
kenttiä käytetään.
Tämä hiuksenhieno ero kenttien välillä ja menetelmiä on nimenomaan JavaScript –
Onneksi tämä ongelma näyttäytyy ainoastaan, jos ohittaa kenttä on käytetty vanhemman rakentaja., Silloin voi olla vaikea ymmärtää, mistä on kyse, joten selitämme asiaa tässä.
Jos siitä tulee ongelma, sen voi korjata peltojen sijaan menetelmillä tai gettereillä / settereillä.
Super: sisäosat, ]
Jos luet opetusohjelma ensimmäistä kertaa – tämä osio voidaan ohittaa.
se kertoo perinnön taustalla olevista sisäisistä mekanismeista ja super
.
mennään hieman syvemmälle alla huppu super
. Matkan varrella nähdään mielenkiintoisia asioita.,
ensin sanoa, kaikesta siitä, mitä olemme oppineet tähän asti, on mahdotonta, että super
toimisi ollenkaan!
Joo, todellakin, kysytään itseltämme, miten sen pitäisi teknisesti toimia? Kun kohde menetelmä toimii, se saa nykyisen objektin this
. Jos me kutsumme super.method()
sitten, moottori tarvitsee saada method
prototyyppi nykyisen objektin. Mutta miten?
tehtävä voi tuntua yksinkertaiselta, mutta se ei ole., Moottori tietää nykyinen objekti this
, niin se voisi saada vanhemman method
kuten this.__proto__.method
. Valitettavasti tällainen ”naiivi” ratkaisu ei toimi.
näytetään ongelma. Ilman luokkia, käyttämällä yksinkertaisia esineitä yksinkertaisuuden vuoksi.
Voit ohittaa tämän osan ja mennä alla ]
alaluokka, jos et halua tietää yksityiskohtia. Siitä ei ole haittaa. Tai lue eteenpäin, jos olet kiinnostunut ymmärtämään asioita syvällisesti.
alla olevassa esimerkissä rabbit.__proto__ = animal
., Nyt kokeillaan: in rabbit.eat()
soitamme animal.eat()
käyttäen this.__proto__
:
linja (*)
otamme eat
prototyyppi (animal
) ja puhelun yhteydessä nykyisen objektin. Huomaa, että .call(this)
– on tärkeää täällä, koska yksinkertainen this.__proto__.eat()
olisi suorittaa vanhemman eat
yhteydessä prototyyppi, ei nykyinen objekti.,
ja yllä olevassa koodissa se todella toimii tarkoitetulla tavalla: meillä on oikea alert
.
nyt lisätään vielä yksi esine ketjuun. Katsotaan, miten asiat menevät:
koodi ei toimi enää! Näemme virheen, kun yritämme soittaa longEar.eat()
.
se ei välttämättä ole niin ilmeinen, mutta jos jäljitämme longEar.eat()
soita, niin voimme nähdä miksi. Molempien linjojen (*)
ja (**)
arvo this
on nykyinen objekti (longEar
)., Se on oleellista: kaikki objektimenetelmät saavat nykyisen objektin nimellä this
, ei prototyyppiä tai jotain.
Tässä on kuva siitä, mitä tapahtuu:
ongelmaa ei voi ratkaista käyttämällä this
yksin.
]
tarjota ratkaisu, JavaScript lisää yksi erityinen sisäinen kiinteistön toiminnot: ]
.,
Kun toiminto on määritetty luokan tai esine menetelmä, sen ]
ominaisuus on, että objekti.
Sitten super
käyttää sitä ratkaista vanhempi prototyyppi ja sen menetelmiä.
katsotaanpa, miten se toimii, ensin tavallinen esineitä:
Menetelmät eivät ole ”vapaa”
Kuten olemme aiemmin tunteneet, yleensä toiminnot ovat ”vapaata”, ei ole sidottu esineitä JavaScript. Joten ne voidaan kopioida objektien välillä ja kutsua toisella this
.,
]
olemassaolo rikkoo tätä periaatetta, koska menetelmät muistavat kohteensa. ]
ei voi muuttaa, joten tämä bond on ikuisesti.
ainoa paikka, jossa kieli, jossa ]
käytetään – on super
. Joten, jos menetelmä ei käytä super
, voimme silti pitää sitä vapaana ja kopioida esineiden välillä. Mutta super
asiat saattavat mennä pieleen.,
Tässä on demo väärä super
tulos kopioinnin jälkeen:
kutsu tree.sayHi()
näyttää ”olen eläin”. Ehdottomasti väärin.
syy on yksinkertainen:
Tässä on kaavio siitä, mitä tapahtuu:
Menetelmiä, ei toiminto ominaisuudet
ero voi olla ei-välttämätöntä meille, mutta se on tärkeää, että JavaScript.
alla olevassa esimerkissä vertailussa käytetään ei-metodista syntaksia., ]
omaisuus ei ole asetettu ja perintö ei toimi:
Tiivistelmä
- laajentaa luokka:
class Child extends Parent
:- Joka tarkoittaa
Child.prototype.__proto__
tulee olemaanParent.prototype
, niin menetelmät ovat perineet.
- Joka tarkoittaa
- Kun ylivoimainen rakentaja:
- Meidän täytyy soittaa vanhemman rakentaja kuten
super()
vuonnaChild
rakentaja, ennen kuin käytätthis
.,
- Meidän täytyy soittaa vanhemman rakentaja kuten
- Kun toinen ensisijainen menetelmä:
- voidaan käyttää
super.method()
showChild
tapa soittaaParent
menetelmä.
- voidaan käyttää
- Sisäosat:
- Menetelmät muistaa niiden luokan/olion sisäinen
]
omaisuutta. Näinsuper
ratkaisee vanhempainmenetelmät. - joten ei ole turvallista kopioida menetelmää
super
kohteesta toiseen.,
- Menetelmät muistaa niiden luokan/olion sisäinen
Lisäksi:
- Nuoli toimintoja ei ole omia
this
taisuper
, niin he avoimesti sovi ympäröivään kontekstiin.
Vastaa