![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
How to access extended functionality of an extended member of an extended class?
class Member {...}
class MemberExtended extends Member {
public function doSomethingNew(){...}
}
class Container {
public var m:myMember;
}
class ContainerExtended {
override public function init(){
this.m = new MemberExtended(); // use the subclass.
}
override public function doStuff(){
m.doSomethingNew(); // Error: class Member has no method doSomethingNew
}
}
The error makes sense because this.m is still defined as a Member and the check is run at compile time rather than run time. Haxe does not allow you to override or redefine member declarations, so there seems to be no way to say that the member should be the subclass for all instances of the ContainerExtended class.
I "solved" this by adding doSomethingNew() to the base Member class. This solution is not that good when extending a library class or when desiring to keep the base classes clean and simple.
There is probably a pattern for this situation that I am unaware of.
Reflect.callMethod() works but does away with any kind of compile-time type checking, which I want to keep. Note: The second arg should be Reflect.field(m, "doSomethingNew"), not a simple string. A string would produce the error "builtin::apply not found on Object", which will now have a search result in Google.
Setting the member's type to Dynamic 'works' but has the same drawbacks as using reflection.
Using typedefs produces "Unexpected typedef". I suppose they can't be used in a class.
Another bad solution is to have instances of both Member and MemberExtended classes, which is an easy way to add bugs to the program.
There might be a general problem with extending member variables when considering how classes might be laid out at the low level. In an old language like C, the members of a struct would be laid out in order in one flat array of bytes. Member access would use a byte offset, copying a class would be a simple memcpy operation, and casting would be a no-op. Extending one of the member variables could change the class's byte size and break compatibility with the parent class. Newer languages might avoid this problem by using hash functions for member access and some kind of reflection-based copying mechanism, which makes the language slower for these operations but increases flexibility.
http://www.coderanch.com/t/522426/java/java/Extending-classes-member-variables-extended
Space really is the final frontier. I cannot extend the Space class [from the Nape library]. I think I'll create a SpaceController class instead.
The goal is to detach everything happening in the game from the main class so that main can be a controller which can switch between Spaces at will.
Still working on it; ran into a severe case of the above inheritance problem.
Potential solutions:
Add another controller object
Make the "extension" a controller that contains the extended function and a reference to the Member class instance. In the long run, this leads to having ControllerControllerControllerControllers.This is called the Decorator pattern.
Erich Gamma's Extension Objects Pattern
Give every class a function GetExtension(str) that returns Extension. Or just use an associative array of extension names => extension class instances. The caller will have to dynamically cast the result and check for errors. This reimplements what should be core syntax.Visitor pattern
Give every class a function accept(Visitor) that calls Visitor.visit(), which is defined later.