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.,

Mitään ilmaisu on sallittua, kun 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ät this.

… 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ää sen this.
  • 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

Lisäasetukset huomautus

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, ]

lisätiedot

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ä

  1. laajentaa luokka: class Child extends Parent:
    • Joka tarkoittaa Child.prototype.__proto__ tulee olemaan Parent.prototype, niin menetelmät ovat perineet.
  2. Kun ylivoimainen rakentaja:
    • Meidän täytyy soittaa vanhemman rakentaja kuten super() vuonna Child rakentaja, ennen kuin käytät this.,
  3. Kun toinen ensisijainen menetelmä:
    • voidaan käyttää super.method() show Child tapa soittaa Parent menetelmä.
  4. Sisäosat:
    • Menetelmät muistaa niiden luokan/olion sisäinen ] omaisuutta. Näin super ratkaisee vanhempainmenetelmät.
    • joten ei ole turvallista kopioida menetelmää super kohteesta toiseen.,

Lisäksi:

  • Nuoli toimintoja ei ole omia this tai super, niin he avoimesti sovi ympäröivään kontekstiin.