arv - Hvordan kan jeg gjøre konstruktør-overlasting i en avledet klasse i TypeScript?
Forutsatt at jeg har en 'base'-klasse som dette:
class CcDefinition {
// Some properties here
constructor (json: string);
constructor (someVar: number, someOtherVar: string);
constructor (jsonOrSomeVar: any, someOtherVar?: string) {
if (typeof jsonOrSomeVar=== "string") {
// some JSON wrangling code here
} else {
// assign someVar and someOtherVar to the properties
}
}
}
Jeg vil kunne utvide denne baseklassen samtidig som jeg støtter konstruktør-overbelastning. For eksempel:
class CcDerived extends CcDefinition {
// Some additional properties here
constructor (json: string);
constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
if (typeof jsonOrSomeVar=== "string") {
super.constructFromJson(jsonOrSomeVar);
} else {
super.constructFromDef(someOtherVar, someAdditionalVar);
// assign someVar to the additional properties of this derived class
}
}
}
Problemet er at Typescript krever at nøkkelordet 'super' skal komme først (bokstavelig talt) i konstruktørimplementeringen. Den spesifikke byggefeilmeldingen er:
"Et 'super'-kall må være den første setningen i konstruktøren når en klasse inneholder initialiserte egenskaper eller har parameter-egenskaper."
Imidlertid må jeg fastslå hvilke parametere jeg vil sende inn i 'super' (dvs. bruke en annen konstruktøroverlasting) basert på hva som ble levert til den utvidede (avledede) klassen. Du bør her anta at konstruktøroverlastingene til den avledede klassen kan være veldig forskjellige fra superklassens.
Finnes det en løsning på det jeg prøver å oppnå?
Svar #1
Denne begrensningen gjelder bare hvis du har initialisert medlemsvariabler i den avledede klassen, så den første løsningen er enkelt å bare deklarere disse variablene og deretter initialisere dem i konstruktøren til den avledede klassen.
Med andre ord, du kan endre:
class CcDerived extends CcDefinition {
y = 10;
constructor (json: string);
constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
if (typeof jsonOrSomeVar=== "string") {
super(jsonOrSomeVar);
} else {
super(someOtherVar, someAdditionalVar);
}
}
}
til dette:
class CcDerived extends CcDefinition {
// Some additional properties here
y: number;
constructor (json: string);
constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
this.y = 10;
if (typeof jsonOrSomeVar=== "string") {
super(jsonOrSomeVar);
} else {
super(someOtherVar, someAdditionalVar);
}
}
}
Merk at initialiseringsrekkefølgen her er omtrent den samme som i andre OOP-språk, og du må være forsiktig med å ikke kalle virtuelle metoder fra konstruktører, osv.
Hvis det er for frastøtende, merk at begrensningen rett og slett er at den første setningen må være et superkall. Du kan ofte omstrukturere superkallet:
class CcDerived extends CcDefinition {
constructor (json: string);
constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
super(
typeof jsonOrSomeVar === 'string' ? jsonOrSomeVar : someOtherVar,
typeof jsonOrSomeVar === 'string' ? undefined : someAdditionalVar);
}
}
Ikke den peneste, men den er i det minste semantisk ekvivalent. Dette forutsetter at konstruktøren i basis-klassen din sjekker etter undefined (i stedet for arguments.length) for å avgjøre hvilken overbelastning som ble kalt.
