How to dynamically call constructor, based on class name?

Hi!
Working on a website, using Haxe, with a JavaScript target.
I have a question:

Suppose I have a class “Base”, and a number of descendent classes:

class Base {
  //
}

class Desc1 extends Base {
  //
}

class Desc2 extends Base {
  //
}

class Desc3 extends Base {
  //
}

Now suppose I have a string, loaded at runtime, that contains the name of any one of those descendent classes:

var s: String;
… // Loading happens...
trace(s); // E.g., 'Desc2'

What I want to do is create an object, of declared type Base, at runtime, with the name of its runtime type corresponding to that string:

var o: Base = new …; // o has now type Desc2

How do I dynamically call that particular descendent constructor (in this case, new Desc2()), going ONLY by the name in that string?

Many thanks!

See Type.createInstance() and Type.createEmptyInstance(), which you should be able to feed Type.resolveClass(s) to.

Edit: note that those will need to be included in the compilation. Make sure you include those types (you might need to add a reference to them in your hxml or reference them somewhere. You also need to make sure dce (dead code elimination) doesn’t get rid of them; that can be done by adding @:keep to those types.

1 Like

If you don’t want to rely on reflection, a simple Map can work:

var constructors = [
  "Desc1" => Desc1.new,
  "Desc2" => Desc2.new,
  // etc
];
var s:String = ...;
// maybe check that constructors contains s ?
var o:Base = constructors[s]();

You can use macros to generate the constructors expression automatically, e.g. for all classes in a given package. Since all the child classes are mentioned in the code, there should be no need to annotate them with @:keep.

3 Likes

Awesome, awesome, awesome!
This solved it, many many thanks.
Keep safe,
Matt