TypeScript åtkomst till statisk egenskap på underklass
Jag använder TypeScript för att representera en komplex modell i OOP-form. Det finns en föräldraklass Base som sätter vissa värden som används i nästan varje klass så att jag inte har repetitiv kod.
Jag använder npm-paketet debug för felsökningsloggning och hoppas att ha loggar som ser ut ungefär så här:
mypkg:DataModel:0 This is the first time I ran new DataModel().
mypkg:OtherMdls:0 And this is the first time I ran new OtherMdls().
mypkg:DataModel:1 This is a log from the second instance of DataModel.
Jag får detta resultat genom att låta den abstrakta basklassen lagra en static _instanceID-egenskap och en private _instanceID-egenskap som liknar denna:
abstract class Base {
static _instanceID = 0;
private _instanceID;
protected _log: debug.Debugger;
constructor() {
this._instanceID = Base._instanceID++;
this._log = debug(`mypkg:${this.constructor.name}:${this._instanceID}`);
}
}
Värdet this.constructor.name verkar lösas till vad klassen som skapats heter, vilket resulterar i den typ av logg jag vill ha, oavsett hur många gånger klassen är ärvd.
Problemet är, låt oss skapa några extra tomma klasser:
class A extends Base {}
class B extends Base {}
class C extends Base {}
Nu ska jag skapa några av varje av dessa klasser och logga deras _instanceID-värden.
new A(); // _instanceID = 0 ; expected
new A(); // _instanceID = 1 ; expected
new B(); // _instanceID = 2 ; what? expected 0
Jag förstår logiken här. Base-klassen använder sitt eget _instanceID på grund av denna rad:
this._instanceID = Base._instanceID++;
// ^^^^
Nu vill jag egentligen öka den statiska _instanceID på den ärvande klassen, så att jag får resultat som liknar:
new A(); // 0
new A(); // 1
new B(); // 0
new C(); // 0
new B(); // 1
new A(); // 1
new C(); // 1
new C(); // 2
Du förstår poängen vid det här laget. Hur kan jag fixa det här?
Även, utan att skicka egenskaper i super()-anropet, är det möjligt att få loggarna att visa alla ärvda klasser, liknande mypkg:DataModel:SubModel:Thing:0 eller blir detta för omfattande och kan det bara vara mypkg:DataModel:0?
Svar #1
Ett alternativ skulle vara att referera till constructor för det statiska id:et, på liknande sätt som du använder det för att hämta namnet.
Nackdelen är att det för närvarande inte finns några bra sätt att härleda typen av constructor. Den länkade frågan visar dock några alternativ som fungerar som en lösning.
class Base {
static _instanceID = 0;
_instanceID;
constructor() {
this._instanceID = this.constructor._instanceID++;
console.log(this.constructor.name, this._instanceID);
}
}
class A extends Base {}
class B extends Base {}
class C extends Base {}
new A(); // 0
new A(); // 1
new A(); // 2
new B(); // 0
new B(); // 1
new C(); // 0
new C(); // 1
new C(); // 2