Kan ikke henvise til “X” før supertype-konstruktør er blevet kaldt op

1. Oversigt

I denne korte vejledning viser vi, hvordan vi kan få fejlen Kan ikke henvise til "X" før supertypekonstruktøren er blevet kaldt, og hvordan man undgår det.

2. Konstruktionskæde

En konstruktør kan kalde nøjagtigt en anden konstruktør. Dette opkald skal være i første linje i dets krop.

Vi kan ringe til en konstruktør af samme klasse med nøgleordet det her, eller vi kan kalde en konstruktør af superklassen med nøgleordet super.

Når en konstruktør ikke kalder en anden konstruktør, tilføjer compileren et opkald til superklassens konstruktør uden argument.

3. Vores kompileringsfejl

Denne fejl koger ned til forsøger at få adgang til instansniveau medlemmer, før vi påberåber konstruktorkæden.

Lad os se et par måder, vi kan løbe ind på dette.

3.1. Henvisning til en instansmetode

I det næste eksempel ser vi kompileringsfejlen Kan ikke henvise til "X", før supertype-konstruktør er blevet kaldt på linje 5. Bemærk, at konstruktøren forsøger at bruge instansmetoden getErrorCode () for tidligt:

offentlig klasse MyException udvider RuntimeException {private int errorCode = 0; offentlig MyException (streng besked) {super (besked + getErrorCode ()); // kompileringsfejl} offentlig int getErrorCode () {return errorCode; }} 

Disse fejl, fordi until super() har afsluttet, der er ikke en forekomst af klassen MyException. Derfor kan vi endnu ikke ringe til instansmetoden getErrorCode ().

3.2. Henvisning til et instansfelt

I det næste eksempel ser vi vores undtagelse med et instansfelt i stedet for en instansmetode. Lad os se på hvordan den første konstruktør prøver at bruge et instansmedlem, før selve forekomsten er klar:

offentlig klasse MyClass {private int myField1 = 10; privat int myField2; offentlig MyClass () {denne (myField1); // kompileringsfejl} offentlig MyClass (int i) {myField2 = i; }}

En henvisning til et instansfelt kan kun foretages, når klassen er initialiseret, hvilket betyder efter et kald til det her() eller super().

Så hvorfor er der ingen kompilatorfejl i den anden konstruktør, som også bruger et instansfelt?

Huske på, at alle klasser stammer implicit fra klasse Objekt, og så er der en implicit super() opkald tilføjet af compileren:

offentlig MyClass (int i) {super (); // tilføjet af kompilator myField2 = i; } 

Her, Objekt'S konstruktør bliver kaldt, før vi får adgang myField2, hvilket betyder, at vi er okay.

4. Løsninger

Den første mulige løsning på dette problem er trivielt: vi kalder ikke den anden konstruktør. Vi gør eksplicit i den første konstruktør, hvad vi ønskede at gøre i den anden konstruktør.

I dette tilfælde kopierede vi værdien af myField1 ind i myField2:

offentlig klasse MyClass {private int myField1 = 10; privat int myField2; offentlig MyClass () {myField2 = myField1; } offentlig MyClass (int i) {myField2 = i; }} 

Generelt dog vi er sandsynligvis nødt til at genoverveje strukturen i det, vi bygger.

Men hvis vi ringer til den anden konstruktør af en god grund, for eksempel for at undgå at gentage kode, vi kan flytte koden til en metode:

offentlig klasse MyClass {private int myField1 = 10; privat int myField2; offentlig MyClass () {setupMyFields (myField1); } offentlige MyClass (int i) {setupMyFields (i); } privat ugyldigt setupMyFields (int i) {myField2 = i; }} 

Igen fungerer dette, fordi compileren implicit har kaldt konstruktorkæden, inden den påberåber sig metoden.

En tredje løsning kan være, at vi bruger statiske felter eller metoder. Hvis vi ændrer os myField1 til en statisk konstant, så er compileren også glad:

offentlig klasse MyClass {privat statisk endelig int SOME_CONSTANT = 10; privat int myField2; offentlig MyClass () {denne (SOME_CONSTANT); } offentlig MyClass (int i) {myField2 = i; }} 

Vi skal bemærke, at lave et felt statisk betyder, at det bliver delt med alle forekomster af dette objekt, så det er ikke en ændring at gøre for let.

Til statisk For at være det rigtige svar har vi brug for en stærk grund. For eksempel er værdien måske ikke rigtig et felt, men i stedet en konstant, så det giver mening at gøre det statisk og endelig. Måske behøver den byggemetode, vi ønskede at kalde, ikke adgang til instansmedlemmerne i klassen, hvilket betyder, at den skulle være statisk.

5. Konklusion

Vi så i denne artikel, hvordan man henviser til instansmedlemmer før super() eller det her() opkald giver en kompileringsfejl. Vi så dette ske med en eksplicit erklæret basisklasse og også med den implicitte Objekt basisklasse.

Vi demonstrerede også, at dette er et problem med konstruktionsdesignet og viste, hvordan dette kan løses ved at gentage kode i konstruktøren, delegere til en installationsmetode efter konstruktion eller brugen af ​​konstante værdier eller statiske metoder til at hjælpe med konstruktionen .

Som altid kan kildekoden til dette eksempel findes på GitHub.


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