[personal profile] tangaroa
In languages based on message-passing, you just call the function and an error will occur at run time if it does not exist. In languages with reflection, you can test to see if the function exists and then call it. In Haxe...

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.

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting
Page generated Jul. 12th, 2025 11:03 pm
Powered by Dreamwidth Studios