Class öröklés egy módja annak, hogy az egyik osztály kiterjeszteni egy másik osztály.
így új funkciókat hozhatunk létre a meglévő tetején.
A “kiterjed” kulcsszó
mondjuk az osztály Animal
:
Itt van, hogyan tudjuk képviselni animal
objektumot, majd a Animal
class grafikusan:
…szeretnénk, hogy létrehoz egy class Rabbit
.,
mivel a nyulak állatok, osztály kell alapulnia Animal
, hozzáférhetnek az állati módszerek, így a nyulak meg tudják csinálni, amit a “generikus” állatok tehet.
egy másik osztály kiterjesztésének szintaxisa: class Child extends Parent
.
hozzunk létre class Rabbit
, amely a Animal
:
Rabbit
osztály mind a Rabbit
módszerekhez, például rabbit.hide()
, valamint Animal
módszerek, például rabbit.run()
.,
belsőleg, extends
kulcsszó működik a jó öreg prototípus mechanika. Rabbit.prototype.]
Animal.prototype
. Tehát, ha egy módszer nem található a Rabbit.prototype
– ban, a JavaScript a Animal.prototype
– ből veszi.,
például a rabbit.run
módszer megtalálásához a motor ellenőrzi (alulról felfelé a képen):
amint a fejezetből emlékeztetünk natív prototípusok, maga a JavaScript prototípus örökséget használ a beépített objektumokhoz. Pl. Date.prototype.]
is Object.prototype
. Ezért a dátumok hozzáférhetnek az Általános objektummódszerekhez.,
extends
osztály szintaxis lehetővé teszi, hogy adja meg nem csak egy osztály, de minden kifejezés után.
például egy függvény hívását generál a szülő osztály:
function f(phrase) { return class { sayHi() { alert(phrase); } };}class User extends f("Hello") {}new User().sayHi(); // Hello
Itt class User
örökli az az eredménye, hogy a f("Hello")
.,
Ez hasznos lehet a fejlett programozási mintákhoz, amikor függvényeket használunk osztályok generálására, sok feltételtől függően, és örökölhetnek tőlük.
egy metódus felülbírálása
most lépjünk előre és felülírjuk a metódust. Alapértelmezés szerint minden olyan módszer, amely nincs megadva a class Rabbit
– ban, közvetlenül “a class Animal
– ból származik.,
De ha adja meg a saját módszer a Rabbit
, mint stop()
akkor lesz használva helyette:
class Rabbit extends Animal { stop() { // ...now this will be used for rabbit.stop() // instead of stop() from class Animal }}
Általában nem akarjuk, hogy teljesen cserélje ki egy szülő módszer, hanem inkább az, hogy építeni a tetején, hogy a csípés, vagy bővíteni a funkcionalitást. Teszünk valamit a módszerünkben, de hívjuk a szülő módszert előtte / utána vagy a folyamatban.
osztályok "super"
kulcsszó, hogy.
-
super.method(...)
szülő módszer hívásához., -
super(...)
egy szülő konstruktor hívásához (csak a konstruktorunkon belül).
például hagyjuk, hogy a nyúl autohid amikor megállt:
most van a módszer, amely felhívja a szülősuper.stop()
a folyamat.
felülbíráló konstruktor
a konstruktorok kap egy kicsit trükkös.
mostanáig, Rabbit
nem volt saját constructor
.,
specifikáció Szerint, ha egy osztály kiterjeszti egy másik osztály pedig nem constructor
, akkor a következő az “üres” constructor
keletkezik:
class Rabbit extends Animal { // generated for extending classes without own constructors constructor(...args) { super(...args); }}
Mint láthatjuk, alapvetően felhívja a szülő constructor
halad az érveket. Ez akkor történik, ha nem írunk saját konstruktort.
most adjunk hozzá egy egyéni konstruktort a Rabbit
– hoz. A earLength
name
:
, Hiba történt. Most nem hozhatunk létre nyulakat. Mi történt rosszul?
a rövid válasz:
- az öröklő osztályok Konstruktorainak
super(...)
, és (!) athis
használata előtt tegye meg.
… de miért? Mi folyik itt? Valójában a követelmény furcsanak tűnik.
természetesen van magyarázat. Nézzünk bele a részletekbe, hogy tényleg megértsd, mi folyik itt.
A JavaScriptben különbséget lehet tenni az öröklő osztály (ún. “származtatott konstruktor”) és más függvények konstruktorfüggvénye között., A származtatott konstruktornak van egy speciális belső tulajdonsága ]:"derived"
. Ez egy különleges belső címke.
Ez a címke befolyásolja a viselkedését new
.
- ha egy szabályos függvény
new
segítségével kerül végrehajtásra, akkor egy üres objektumot hoz létre, ésthis
– hoz rendeli. - de ha egy származtatott konstruktor fut, akkor ezt nem teszi meg. Elvárja, hogy a szülő konstruktor ezt a munkát.,
tehát egy származtatott konstruktornak meg kell hívnia a super
– t a szülő (alap) konstruktor végrehajtásához, különben a this
objektum nem jön létre. És hibát követünk el.
a Rabbit
kivitelező dolgozni kell hívni super()
, mielőtt a this
, mint itt:
Nyomós osztály mezőket: egy trükkös megjegyzés:
Ez a megjegyzés feltételezi, hogy egy bizonyos tapasztalatok osztályok, talán más programozási nyelvek.,
jobb betekintést nyújt a nyelvbe, valamint elmagyarázza azt a viselkedést is, amely a hibák forrása lehet (de nem túl gyakran).
Ha nehezen érthető, csak folytassa, folytassa az olvasást, majd térjen vissza egy kicsit később.
nem csak a módszereket, hanem az osztálymezőket is felülbírálhatjuk.
bár, van egy trükkös viselkedés, amikor elérjük a felülbírált mező szülő konstruktor, egészen más, mint a legtöbb más programozási nyelvek.,
Tekintsük ezt a példát:
itt, class extends Animal
és felülírja name
mezőt saját értékével.
nincs saját konstruktor a – ban, így a Animal
konstruktor neve.
ami érdekes, hogy mindkét esetben: new Animal()
és new Rabbit()
, a alert
a (*)
animal
.,
más szóval, a szülő konstruktor mindig a saját mező értékét használja, nem pedig a felülírottat.
mi a furcsa benne?
Ha még nem világos, kérjük, hasonlítsa össze a módszereket.
itt ugyanaz a kód, de athis.name
mező helyettthis.showName()
módszer:
megjegyzés: most a kimenet más.
és természetesen erre számítunk. Amikor a szülő konstruktort a származtatott osztályba hívják, akkor a felülbírált módszert használja.
… de az osztálymezők esetében ez nem így van. Mint mondta, a szülő konstruktor mindig a szülő mezőt használja.,
miért van különbség?
Nos, az ok a mező inicializálási sorrendjében van. Az osztály mező inicializálva van:
- az alaposztály konstruktora előtt (ez nem terjed ki semmire),
- közvetlenül a
super()
után a származtatott osztályhoz.
esetünkben A származtatott osztály. Nincs benne constructor()
. Mint korábban említettük, ez ugyanaz, mintha egy üres konstruktor lenne, csak super(...args)
.,
So, new Rabbit()
hívások super()
, így végrehajtva a szülő konstruktort, és (a származtatott osztályok szabálya szerint) csak azt követően, hogy az osztálymezők inicializálásra kerülnek. A szülő konstruktor végrehajtásakor még nincsenek Rabbit
osztálymezők, ezért használják a Animal
mezőket.
Ez a finom különbség mezők és módszerek specifikus JavaScript
szerencsére, ez a viselkedés csak akkor derül ki, ha egy felülbírált mező használják a szülő konstruktor., Akkor lehet, hogy nehéz megérteni, mi folyik itt, ezért itt magyarázzuk meg.
ha problémává válik, akkor a mezők helyett módszerekkel vagy getterekkel/setterekkel lehet kijavítani.
Super: internals,]
ha először olvassa el a bemutatót-ez a szakasz kihagyható.
az öröklés mögötti belső mechanizmusokról és super
.
let ‘ s get a little deeper under the hood of super
. Látni fogunk néhány érdekes dolgot az út mentén.,
először is, mindaz, amit eddig megtanultunk, lehetetlen super
egyáltalán dolgozni!
igen, valóban, kérdezzük meg magunktól, hogyan kell technikailag működnie? Ha egy objektum metódus fut, akkor az aktuális objektumot this
– ként kapja meg. Ha super.method()
– nak hívjuk, akkor a motornak a method
– t kell beszereznie az aktuális objektum prototípusából. De hogyan?
a feladat egyszerűnek tűnhet, de nem az., A motor ismeri az aktuális objektumot this
, így megkaphatja a szülőt method
as this.__proto__.method
. Sajnos egy ilyen “naiv” megoldás nem fog működni.
mutassuk be a problémát. Osztályok nélkül, egyszerű tárgyak használata az egyszerűség kedvéért.
ezt a részt kihagyhatja, és a]
alszakaszra léphet, ha nem szeretné tudni a részleteket. Az nem fog ártani. Vagy olvassa el, ha érdekli a dolgok mélyreható megértése.
az alábbi példában rabbit.__proto__ = animal
., Most próbáljuk meg: a rabbit.eat()
fogjuk hívni animal.eat()
, a this.__proto__
:
a (*)
vesszük eat
a prototípusból (animal
), majd az aktuális objektum összefüggésében hívja. Kérjük, vegye figyelembe, hogy a.call(this)
itt fontos, mert egy egyszerűthis.__proto__.eat()
végrehajtja a szülőteat
a prototípus összefüggésében, nem az aktuális objektum.,
és a fenti kódban valóban rendeltetésszerűen működik: megvan a helyes alert
.
most adjunk hozzá még egy objektumot a lánchoz. Meglátjuk, hogyan törnek a dolgok:
a kód már nem működik! Láthatjuk a hibát próbál hívni longEar.eat()
.
lehet, hogy nem olyan nyilvánvaló, de ha nyomon követjük a longEar.eat()
hívást, akkor láthatjuk, miért. Mindkét sorban (*)
és (**)
a this
értéke az aktuális objektum (longEar
)., Ez elengedhetetlen: minden objektummódszer az aktuális objektumot this
– ként kapja meg, nem prototípus vagy valami.
itt van a kép arról, hogy mi történik:
a problémát önmagában athis
használatával nem lehet megoldani.
]
a megoldás biztosításához a JavaScript még egy speciális belső tulajdonságot ad a funkciókhoz: ]
.,
Ha egy függvény osztály vagy objektum metódusként van megadva, akkor a]
tulajdonság lesz az objektum.
majd super
a szülő prototípusának és módszereinek megoldására használja.
lássuk, hogyan működik, először egyszerű objektumokkal:
A módszerek nem ” ingyenesek “
mint korábban ismert, általában a funkciók” ingyenesek”, nem kötődnek a JavaScript objektumaihoz. Így lehet másolni az objektumok között, és hívni egy másik this
.,
a]
létezése sérti ezt az elvet, mert a módszerek emlékeznek tárgyaikra. ]
nem lehet megváltoztatni, így ez a kötés örökre.
az egyetlen hely a nyelvben, ahol]
használják – super
. Tehát, ha egy módszer nem használ super
, akkor továbbra is szabadnak tekinthetjük, és másolhatjuk az objektumok között. De a super
a dolgok rosszul fordulhatnak.,
itt van a demo egy rosszsuper
eredmény másolás után:
a hívástree.sayHi()
mutatja “állat vagyok”. Határozottan rossz.
az ok egyszerű:
itt van a diagram, hogy mi történik:
div>
módszerek, nem függvénytulajdonságok
a különbség nem feltétlenül szükséges számunkra, de fontos a JavaScript számára.
az alábbi példában egy nem metódus szintaxist használunk összehasonlításra., ]
a tulajdonság nincs beállítva, és az örökség nem működik:
összefoglaló
- egy osztály kiterjesztéséhez:
class Child extends Parent
:- ez azt jelenti, hogy
Child.prototype.__proto__
Parent.prototype
, így a módszerek öröklődnek.
- ez azt jelenti, hogy
- amikor felülírja a konstruktor:
- meg kell hívni szülő konstruktor, mint
super()
inChild
konstruktor használata előttthis
.,
- meg kell hívni szülő konstruktor, mint
- ha felülír egy másik módszer:
- tudjuk használni
super.method()
aChild
módszer hívjaParent
módszer.
- tudjuk használni
- Internals:
- Methods remember their class/object in the internal
]
property. Így oldja meg asuper
szülői módszereket. - tehát nem biztonságos másolni egy módszert a
super
egyik objektumról a másikra.,
- Methods remember their class/object in the internal
is:
- a Nyílfüggvényeknek nincs saját
this
vagysuper
, így átláthatóan illeszkednek a környező környezetbe.
© 2021 Tombouctou
Theme by Anders Noren — Up ↑
Vélemény, hozzászólás?