Nemôže odkazovať na „X“ predtým, ako bol zavolaný konštruktér supertypu

1. Prehľad

V tomto krátkom tutoriáli si ukážeme, ako môžeme dostať chybu Nemôže odkazovať na „X“ predtým, ako sa volá konštruktor supertypu, a ako sa tomu vyhnúť.

2. Reťaz konštruktérov

Konštruktér môže volať presne jedného iného konštruktora. Tento hovor musí byť v prvom riadku jeho tela.

S kľúčovým slovom môžeme zavolať konštruktor rovnakej triedy toto, alebo môžeme kľúčovým slovom zavolať konštruktor nadtriedy Super.

Keď konštruktor nevolá iného konštruktora, kompilátor pridá volanie konštruktoru bez argumentov nadtriedy.

3. Naša chyba kompilácie

Táto chyba sa zníži na Skúšame získať prístup k členom na úrovni inštancie skôr, ako vyvoláme reťazec konštruktora.

Pozrime sa na niekoľko spôsobov, ako by sme to mohli naraziť.

3.1. Odkazujúce na inštančnú metódu

V nasledujúcom príklade uvidíme chybu kompilácie Pred volaním konštruktora supertypu sa nedá odkazovať na „X“ na riadku 5. Upozorňujeme, že konštruktor sa pokúša použiť inštančnú metódu getErrorCode () príliš skoro:

verejná trieda MyException rozširuje RuntimeException {private int errorCode = 0; public MyException (String message) {super (message + getErrorCode ()); // chyba kompilácie} public int getErrorCode () {return errorCode; }} 

Toto chyby, pretože until Super() dokončil, neexistuje inštancia triedy MyException. Preto ešte nemôžeme volať na inštančnú metódu getErrorCode ().

3.2. Odkazuje na pole inštancie

V nasledujúcom príklade vidíme našu výnimku s inštančným poľom namiesto inštančnej metódy. Poďme sa pozrieť na to, ako prvý konštruktor sa pokúsi použiť člena inštancie skôr, ako je pripravená samotná inštancia:

verejná trieda MyClass {private int myField1 = 10; private int myField2; public MyClass () {this (myField1); // chyba kompilácie} public MyClass (int i) {myField2 = i; }}

Odkaz na pole inštancie je možné urobiť až po inicializácii jeho triedy, to znamená po akomkoľvek volaní na toto () alebo Super().

Prečo teda v druhom konštruktore, ktorý tiež používa pole inštancie, nie je chyba kompilátora?

Zapamätaj si to všetky triedy sú implicitne odvodené od triedy Objekt, a teda existuje implicitné Super() hovor pridaný prekladačom:

public MyClass (int i) {super (); // pridal kompilátor myField2 = i; } 

Tu, ObjektPred prístupom sa zavolá konštruktor myField2, čo znamená, že sme v poriadku.

4. Riešenia

Prvé možné riešenie tohto problému je triviálne: druhého konštruktora nevoláme. V prvom konštruktore robíme výslovne to, čo sme chceli robiť v druhom konštruktore.

V takom prípade by sme skopírovali hodnotu myField1 do myField2:

verejná trieda MyClass {private int myField1 = 10; private int myField2; public MyClass () {myField2 = myField1; } public MyClass (int i) {myField2 = i; }} 

Všeobecne však platí, že pravdepodobne musíme prehodnotiť štruktúru toho, čo staviame.

Ale ak voláme druhého konštruktora napríklad z dobrého dôvodu, aby sme sa vyhli opakovaniu kódu, môžeme presunúť kód do metódy:

verejná trieda MyClass {private int myField1 = 10; private int myField2; public MyClass () {setupMyFields (myField1); } public MyClass (int i) {setupMyFields (i); } private void setupMyFields (int i) {myField2 = i; }} 

Opäť to funguje, pretože kompilátor pred vyvolaním metódy implicitne zavolal reťazec konštruktora.

Tretie riešenie by mohlo byť to, ktoré použijeme statické polia alebo metódy. Ak sa zmeníme myField1 na statickú konštantu, potom je kompilátor tiež šťastný:

verejná trieda MyClass {súkromný statický konečný int SOME_CONSTANT = 10; private int myField2; public MyClass () {this (SOME_CONSTANT); } public MyClass (int i) {myField2 = i; }} 

Mali by sme poznamenať, že vytvorenie poľa statický Znamená, že je zdieľaný so všetkými inštanciami tohto objektu, takže to nie je zmena, ktorú treba robiť príliš ľahko.

Pre statický ako správna odpoveď potrebujeme pádny dôvod. Napríklad možno nie je hodnota pole, ale konštanta, takže má zmysel ju robiť statický a konečné. Možno konštrukčná metóda, ktorú sme chceli zavolať, nepotrebuje prístup k členom inštancie triedy, to znamená, že by mala byť statický.

5. Záver

V tomto článku sme videli, ako urobiť odkaz na členov inštancie pred Super() alebo toto () volanie dáva chybu kompilácie. Videli sme to pri explicitne deklarovanej základnej triede a tiež pri implicitnej Objekt základná trieda.

Tiež sme preukázali, že ide o problém s dizajnom konštruktora, a ukázali sme, ako to možno vyriešiť opakovaním kódu v konštruktore, delegovaním na metódu nastavenia po konštrukcii alebo použitím konštantných hodnôt alebo statických metód na pomoc s konštrukciou. .

Zdrojový kód pre tento príklad ako vždy nájdete na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found