While abstracts don’t exist at runtime, their @:from and @:to functions still need to exist. I’m writing a library that needs to access those functions through reflection.
It seems that most targets can access an abstract’s implementation class at run-time by passing the appropriate string to Type.resolveClass(), like this:
var c = Type.resolveClass("com.example._MyAbstract.MyAbstract_Impl_");
This seems to work for most targets without any special flags or defines. I’ve tried in Neko, HashLink, and Flash so far with success. However, for JavaScript, it does not resolve. Looking at the generated code, it appears that the abstract implementation class is created, but it is never added to $hxClasses where Type.resolveClass() searches. I also tried -D js-es=6, but the generated ES6 code doesn’t make the class available to reflection either.
Is there another API that I can use instead of Type.resolveClass()? Or is there an optional define available that will enable Type.resolveClass() to work on the js target to find abstract implementation classes the same as it does other targets?
Just following up on this to mention that I ended up creating a macro to generate a class with public static methods using a particular naming scheme that allow me to access the abstract’s methods at run-time. It feels a little hacky, but it works well enough. Since I’m already embedding a lot of RTTI data in my app, the size overhead of adding these extra methods doesn’t feel particularly heavy.
abstract Stringy( String ) from String to String {
static public final name = 'Stringy';
public inline function new( s: String ){
this = s;
}
public static function create( s: String ){
return new Stringy( s );
}
@:from
static public function fromArrayInt(a:Array<Int>) {
var s: String = '';
for( i in 0...a.length ){
s += String.fromCharCode( a[i] );
}
return new Stringy(s);
}
@:to
public function toArrayInt() {
var a = new Array<Int>();
if( this == null ) return [-1];
for( i in 0...this.length ){
a[i] = StringTools.fastCodeAt(this,i);
}
return a;
}
}
class Test {
static function main() {
var s1: Null<Stringy> = ( Stringy.name == "Stringy2")? Stringy.create( "how do you do" ): null;
var a1: Array<Int> = s1;
trace(a1);
var s2: Null<Stringy> = ( Stringy.name == "Stringy")? Stringy.create( "how do you do" ): null;
var a2: Array<Int> = s2;
trace( a2 );
}
}
I don’t think that you quite understood what I was asking for.
Using your example, I’d be looking for a way to use reflection to find the class _Stringy.Stringy_Impl_ at run-time. The Haxe compiler generates _Stringy.Stringy_Impl_ from abstract Stringy.
As noted in my original post, Type.resolveClass("_Stringy.Stringy_Impl_") works on most targets, but apparently not with the JS target.