Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haxe - mapping a string to a class

How should I go about mapping a string to a class in Haxe, and then instantiating it?

class Foo{}
class Bar extends Foo{}
class Buzz extends Foo{}

// (...)

var classMap:Map<String, Class<Foo>> = [
    "abc" => Bar,
    "def" => Buzz
];
var myClass:Class<Foo> = classMap["abc"];
var myObj:Foo = new myClass(/* params */);

I thought this would work, but it throws unexpected ( after myClass. What's wrong?

like image 859
Mateusz Sowiński Avatar asked Jan 01 '23 17:01

Mateusz Sowiński


2 Answers

Instead of storing Class<T> in the map and resorting to reflection for instantiation, it's a much nicer pattern to store references to the constructors (using their function type) as detailed in this haxe.org blog post.

class Foo {}
class Bar extends Foo {
    public function new() {}
}
class Buzz extends Foo {
    public function new() {}
}
var constructors:Map<String, Void->Foo> = [
    "abc" => Bar.new,
    "def" => Buzz.new
];
var construct:Void->Foo = constructors["abc"];
var myObj:Foo = construct();

https://try.haxe.org/#49E93

Unlike the Type.createInstance() approach, this doesn't allow you to pass arbitrary arguments to the constructors they might not even accept, so it's much more type-safe. It also automatically works with dead code elimination because Haxe sees that the constructors are referenced.

like image 186
Gama11 Avatar answered Jan 31 '23 08:01

Gama11


You should use Type.createInstance to create an instance of that class. new will only work if you want to directly call the constructor on the Class name itself new Foo()

I suggest you do it this way:

var myClass:Class<Foo> = classMap["abc"];
var myObj:Foo = Type.createInstance(myClass, [/* params */]);

Try it online here: https://try.haxe.org/#3134A

like image 33
Damilare Akinlaja Avatar answered Jan 31 '23 06:01

Damilare Akinlaja