2014-10-02 9 views
7

Supponendo che ho una classe di 'base' come questo:Come posso eseguire il sovraccarico del costruttore in una classe derivata in TypeScript?

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 
    } 
    } 
} 

Voglio essere in grado di estendere questa classe di base, pur sostenendo costruttore sovraccarico. Per esempio:

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 
    } 
    } 
} 

Il problema è che tipografico esige che la parola 'super' compare prima (letteralmente) per l'attuazione del costruttore. Il messaggio di errore specifico di build è:

"Una chiamata 'super' deve essere la prima istruzione nel costruttore quando una classe contiene proprietà inizializzate o ha proprietà parametro."

Tuttavia, ho bisogno di determinare quali parametri passerò nel 'super' (cioè utilizzare un sovraccarico del costruttore diverso) in base a ciò che è stato fornito alla classe estesa (derivata). Qui dovresti assumere che i sovraccarichi del costruttore della classe derivata potrebbero essere molto diversi da quelli del super.

Esiste una soluzione alternativa per ciò che sto cercando di ottenere?

+0

Ecco qualcuno che genera lo stesso problema (senza risoluzione): [http://typescript.codeplex.com/workitem/91] –

risposta

7

Questa limitazione si applica solo se si dispone inizializzato proprietà dei membri della classe derivata, quindi la prima soluzione è semplicemente solo dichiarano quelle proprietà e poi inizializzare nel costruttore della classe derivata.

In altre parole, è possibile cambiare:

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); 
    } 
    } 
} 

a questo:

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); 
    } 
    } 
} 

Nota che l'ordine di inizializzazione qui è più o meno lo stesso che in altre lingue OOP e si deve stare attenti su non chiamare metodi virtuali da costruttori, ecc.

Se questo è troppo spiacevole, nota che la restrizione è semplicemente che la prima dichiarazione essere una super chiamata. Spesso si può fare il refactoring della super chiamata:

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); 
    } 
} 

Non è il più bello, ma è almeno equivalente semanticamente. Ciò presuppone che il costruttore della classe base stia verificando per undefined (anziché arguments.length) per determinare quale sovraccarico è stato richiamato.

+0

Grazie Ryan, avevo già trovato la versione "brutta". Esplorerò anche il tuo primo suggerimento, ma le mie classi attuali potrebbero essere un po 'troppo coinvolte per usarlo effettivamente. –

+0

Non riesco a far funzionare la prima versione con il mio codice. Continuerò a farlo - ma persiste nel riportare l'errore originale. Anche se sia la base che le classi derivate inizializzano i loro membri nel costruttore. –

Problemi correlati