2015-06-13 14 views
16

Quando si chiama un metodo sottoposto a override dal costruttore super-classe, non è possibile ottenere correttamente un valore di una proprietà sub class.Chiamare un metodo sottoposto a override da super-classe in typescript

esempio

class A 
{ 
    constructor() 
    { 
     this.MyvirtualMethod(); 
    } 

    protected MyvirtualMethod(): void 
    { 

    } 
} 

class B extends A 
{ 
    private testString: string = "Test String"; 

    public MyvirtualMethod(): void 
    { 
     alert(this.testString); // This becomes undefined 
    } 
} 

Mi piacerebbe sapere come eseguire l'override correttamente le funzioni a macchina.

+5

Calling metodo virtuale nel costruttore è considerato una cattiva pratica in qualsiasi linguaggio OOP: https://google.com/search?q=virtual+method+in+constructor –

risposta

11

L'ordine di esecuzione è:

  1. A 's costruttore
  2. B' s costruttore

L'assegnazione avviene in B 'costruttore s dopo A' s constructor- _super -ha stato chiamato:

function B() { 
    _super.apply(this, arguments); // MyvirtualMethod called in here 
    this.testString = "Test String"; // testString assigned here 
} 

Così avviene quanto segue:

var b = new B();  // undefined 
b.MyvirtualMethod(); // "Test String" 

Sarà necessario modificare il codice per far fronte a questo. Ad esempio, chiamando lo this.MyvirtualMethod() nel costruttore B, creando un metodo factory per creare l'oggetto e quindi eseguire la funzione, o passando la stringa nel costruttore di A e lavorando in qualche modo ... ci sono molte possibilità.

+0

OO yea .. fatto. Grazie. Ho pensato che la proprietà inizializzasse prima del costruttore. – Sency

+0

Non siamo qui in un caso in cui 'new.target' potrebbe essere utile? – GameAlchemist

24

La chiave sta chiamando il metodo del genitore usando super.methodName();

class A { 
    // A protected method 
    protected doStuff() 
    { 
     alert("Called from A"); 
    } 

    // Expose the protected method as a public function 
    public callDoStuff() 
    { 
     this.doStuff(); 
    } 
} 

class B extends A { 

    // Override the protected method 
    protected doStuff() 
    { 
     // If we want we can still explicitly call the initial method 
     super.doStuff(); 
     alert("Called from B"); 
    } 
} 

var a = new A(); 
a.callDoStuff(); // Will only alert "Called from A" 

var b = new B() 
b.callDoStuff(); // Will alert "Called from A" then "Called from B" 

Try it here

5

Se si vuole una classe super per chiamare una funzione da una sottoclasse, il modo più pulito è quello di definire un modello astratto, in questo modo si conosce in modo esplicito il metodo esiste da qualche parte e deve essere ignorato da una sottoclasse.

Questo è un esempio, di solito non si chiama un metodo sub all'interno del costruttore come istanza secondaria non è ancora inizializzato ... (motivo per cui si dispone di un "indefinito" nell'esempio di tua domanda)

abstract class A { 
    // The abstract method the subclass will have to call 
    protected abstract doStuff():void; 

    constructor(){ 
    alert("Super class A constructed, calling now 'doStuff'") 
    this.doStuff(); 
    } 
} 

class B extends A{ 

    // Define here the abstract method 
    protected doStuff() 
    { 
     alert("Submethod called"); 
    } 
} 

var b = new B(); 

Test it Here

E se proprio come @Max si vuole davvero evitare di implementare il metodo astratto ovunque, basta sbarazzarsi di esso. Non consiglio questo approccio perché potresti dimenticare che stai ignorando il metodo.

abstract class A { 
    constructor() { 
     alert("Super class A constructed, calling now 'doStuff'") 
     this.doStuff(); 
    } 

    // The fallback method the subclass will call if not overridden 
    protected doStuff(): void { 
     alert("Default doStuff"); 
    }; 
} 

class B extends A { 
    // Override doStuff() 
    protected doStuff() { 
     alert("Submethod called"); 
    } 
} 

class C extends A { 
    // No doStuff() overriding, fallback on A.doStuff() 
} 

var b = new B(); 
var c = new C(); 

Provalo Here

+0

Questa soluzione imporrà di definire questo metodo in ogni classe figlia anche se non è necessario. – Max

+0

@Max è l'unico scopo dell'abstract. Ho messo un esempio nella mia risposta per te –

Problemi correlati