Rufen Sie eine überschriebene Methode aus der Superklasse in Typoskript auf

74

Wenn ich eine überschriebene Methode vom Superklassenkonstruktor aufrufe, kann ich den Wert einer Unterklasseneigenschaft nicht korrekt abrufen.

Beispiel

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

Ich möchte wissen, wie man Funktionen in Typoskript korrekt überschreibt.

Sency
quelle
13
Das Aufrufen einer virtuellen Methode im Konstruktor wird in jeder OOP-Sprache als schlechte Praxis angesehen: google.com/search?q=virtual+method+in+constructor
Vitaliy Ulantikov
1
Ich habe die Antwort von @Flavien Volken unten fast verpasst, was mir geholfen hat, dieses Problem zu lösen, nur weil es nicht die 'akzeptierte' Antwort ist (von oben sieht es so aus, als ob es so sein sollte). Bitte überlegen Sie, es für andere zu ändern ...
benshabatnoam

Antworten:

20

Die Reihenfolge der Ausführung ist:

  1. AKonstruktor
  2. BKonstruktor

Die Zuweisung erfolgt im BKonstruktor nach Adem Konstruktor _super- wurde aufgerufen:

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

Also passiert folgendes:

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

Sie müssen Ihren Code ändern, um damit umzugehen. Zum Beispiel durch den Aufruf this.MyvirtualMethod()in B‚s - Konstruktor, durch eine Factory - Methode zu schaffen , das Objekt und führen Sie dann die Funktion, oder indem Sie die Zeichenfolge in erstellen A‘ s Konstruktor und arbeitet , dass aus irgendwie ... es gibt viele Möglichkeiten.

David Sherret
quelle
Sind wir nicht hier in einem Fall, in dem new.targetes nützlich sein könnte?
GameAlchemist
Sprechen wir über Typoskript?
Long Field
120

Der Schlüssel ruft die übergeordnete Methode mit super.methodName () auf.

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"

Probieren Sie es hier aus

Flavien Volken
quelle
2
Auf jeden Fall sollte die "akzeptierte" Antwort sein (fast verpasst, weil es nicht ist). Vielen Dank.
Benshabatnoam
16

Wenn eine Superklasse eine Funktion aus einer Unterklasse aufrufen soll, ist es am saubersten, ein abstraktes Muster zu definieren. Auf diese Weise wissen Sie explizit, dass die Methode irgendwo existiert und von einer Unterklasse überschrieben werden muss.

Dies ist ein Beispiel. Normalerweise rufen Sie keine Submethode innerhalb des Konstruktors auf, da die Subinstanz noch nicht initialisiert ist. (Grund, warum Sie im Beispiel Ihrer Frage ein "undefiniert" haben.)

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

Testen Sie es hier

Und wenn Sie wie @Max wirklich vermeiden möchten, die abstrakte Methode überall zu implementieren, entfernen Sie sie einfach. Ich empfehle diesen Ansatz nicht, da Sie möglicherweise vergessen, dass Sie die Methode überschreiben.

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

Probieren Sie es hier aus

Flavien Volken
quelle
2
Mit dieser Lösung müssen Sie diese Methode in jeder untergeordneten Klasse definieren, auch wenn sie nicht benötigt wird.
Max
3
@ Max es ist der einzige Zweck der Zusammenfassung. Ich habe ein Beispiel in meine Antwort für Sie aufgenommen
Flavien Volken
0

Unten ist ein allgemeines Beispiel

    //base class
    class A {
        
        // The virtual method
        protected virtualStuff1?():void;
    
        public Stuff2(){
            //Calling overridden child method by parent if implemented
            this.virtualStuff1 && this.virtualStuff1();
            alert("Baseclass Stuff2");
        }
    }
    
    //class B implementing virtual method
    class B extends A{
        
        // overriding virtual method
        public virtualStuff1()
        {
            alert("Class B virtualStuff1");
        }
    }
    
    //Class C not implementing virtual method
    class C extends A{
     
    }
    
    var b1 = new B();
    var c1= new C();
    b1.Stuff2();
    b1.virtualStuff1();
    c1.Stuff2();
Moumit
quelle