Reputation: 325
class MySystem extends ListIteratingSystem {
constructor (private creator: EntityCreator) {
super(MyNode, this.updateNode);
}
updateNode() {/* sniiiiip */}
/* sniiiip */
}
In the above code I need some way of passing the updateNode function into to the super call. The compiler complains about this stating that:
Keyword 'this' cannot be referenced in initializers in a class body, or in super constructor calls
Any ideas on how I can work around this? The use case here is that I've abstracted alot of boiler plate code relating to list traversal and such into this base class which is extended by several specific systems that do the real work. The base class needs methods to call on update, add, and remove...
Upvotes: 3
Views: 9211
Reputation: 250882
As of TypeScript 1.3, you can use the protected keyword and late binding so you don't have to pass the method to the super class.
There is still no abstract
keyword, so you would have to supply either default behaviour or throw an exception in your base class - but the protected
keyword allows you to override the base class implementation (the private keyword does not allow this in the current version of TypeScript).
class ListIteratingSystem {
doSomething() {
this.updateNode();
}
protected updateNode() {
alert('Super');
}
}
class MySystem extends ListIteratingSystem {
protected updateNode() {
alert('Sub');
}
}
var a = new ListIteratingSystem();
a.doSomething();
var b = new MySystem();
b.doSomething();
Upvotes: 3
Reputation: 220954
I'm not 100% clear on the semantics of your use case, but you have some options depending on the goals.
First up would be to just define updateNode
/ addNode
/ removeNode
as members of the base class and let the derived classes override them (rather than specifying them as constructor arguments). This is a little less clear for your derived implementations since TypeScript doesn't have a notion of 'abstract', but is probably the cleanest and easiest.
Second would be to refactor a bit and have the derived classes supply a type argument rather than a list of methods, and place the update/add/remove functions in "sister" classes that provide that functionality in a way that lets the base class give them the needed context you would otherwise get from this
. This is more work, but is a much better separation of concerns. If you're trying to accomplish an inversion of control pattern, it's probably better done by composition rather than inheritance.
The last option would be to flip the entire class hierarchy here upside down and move the traversal/etc code into a separate class that these individual implementations would use, essentially de-inverting any inversion of control in the existing code.
I should add that the restriction that you not reference this
in base class constructor argument positions is generally a very good one - attempting to violate it usually means you're setting yourself up for failure further down the road. In this case, if the restriction weren't in place, you'd potentially run in to big trouble when you tried to inherit from MySystem
, or when ListIteratingSystem
decided that it should call updateNode
sometime during construction. FxCop in C# enforces this restriction for this same reason.
Upvotes: 5
Reputation: 12619
Why wont you override a method like this:
class ListIteratingSystem {
execute() {
this.executeOnStart();
};
private executeOnStart() {
throw new Error('This method is abstract');
};
};
class MySystem extends ListIteratingSystem {
constructor (/*...*/) {
super();
}
private executeOnStart() {
alert("derived");
};
}
execution of new MySystem().execute();
displays alert.
Unfortunately there is no nice way to make executeOnStart
method protected abstract
yet. This is a little bit counterintuitive but remember that visibility accessors are only for compilator and intelisence.
Upvotes: 3