Getting all subclasses of a certain class in a macro

185 views
Skip to first unread message

Leonid Darovskikh

unread,
Oct 3, 2017, 2:07:13 AM10/3/17
to Haxe
Hello.

Say, I have a class A, and I want it to have an instance of every subclass of class B as a variable, what is the simplest way to do it?

I was thinking of B having an @:autobuild, that adds every subclass to a static array, accessible by macros, but then I'd have to somehow make sure, that it gets executed before the @:build on A.

Juraj Kirchheim

unread,
Oct 3, 2017, 3:48:32 AM10/3/17
to haxe...@googlegroups.com
You basically can't, because it's a cyclical relationship. I think Haxe has been more liberal about this, but to the best of my understanding in Haxe 4 you cannot type a subclass (and thus run @:autobuild on it) while the superclass is not finished typing. So even if it's possible now, I'm pretty sure it's not going to be in the future.

Also, trying to impose build order usually ends up in a total nightmare. For you and the compiler team ;)

Perhaps you can explain what problem you're trying to solve with this. There might be decent alternatives.

Best,
Juraj

--
To post to this group haxe...@googlegroups.com
http://groups.google.com/group/haxelang?hl=en
---
You received this message because you are subscribed to the Google Groups "Haxe" group.
For more options, visit https://groups.google.com/d/optout.

Leonid Darovskikh

unread,
Oct 3, 2017, 4:13:07 AM10/3/17
to Haxe
AFAIK, there shouldn't be a cyclical relationship, since classes A and B are not related.

Juraj Kirchheim

unread,
Oct 3, 2017, 5:13:05 AM10/3/17
to haxe...@googlegroups.com
Sorry, I misread that. Then there's still the issue of forcing typing of all the relevant subclasses. My previous statement about that still stands though:

> Also, trying to impose build order usually ends up in a total nightmare.


Leonid Darovskikh

unread,
Oct 3, 2017, 7:39:02 AM10/3/17
to Haxe
Is it possible perhaps, to somehow make use of Context.onAfterTyping(...)?

Alexander Kuzmenko

unread,
Oct 6, 2017, 10:45:52 AM10/6/17
to Haxe
Yes, you can define a new type in onAfterTyping with all required data. And then in B resolve that class with Type.resolveClass() (don't forget to add @:keep to the generated class)

вторник, 3 октября 2017 г., 14:39:02 UTC+3 пользователь Leonid Darovskikh написал:

Leonid Darovskikh

unread,
Oct 6, 2017, 5:43:08 PM10/6/17
to Haxe
Well, that's sort of what I was trying to do, however trying to use Context.defineType(...) results in "Type name nrex.core.Dummy is redefined from module nrex.core.Dummy". Here's the function, that gets called on @:build on nrex.core.Game class. I have never used defineType before, that's why the created type is empty.

macro public static function buildGame(): Array<Field>{
Context.onAfterTyping(function(modules: Array<ModuleType> ){
Context.defineType({
fields: [],
isExtern: false,
kind: TDClass(null, [], false),
meta: null,
name: "Dummy",
pack: ["nrex", "core", "Dummy"],
params: null,
pos: Context.currentPos()
});
});

return Context.getBuildFields();

Jason O'Neil

unread,
Oct 6, 2017, 6:56:10 PM10/6/17
to Haxe
It won't help with automatically creating fields on the super class, but you can use CompileTime like this:

var subClasses:List<Class<MySuperClass>> = CompileTime.getAllClasses(MySuperClass);
var subClasses:List<Class<MySuperClass>> = CompileTime.getAllClasses("my.package.only", MySuperClass);

The way it works is using a macro to add metadata that tells CompileTime what the subclasses are, and then at runtime it uses the metadata to get you a list of all of those classes.

That might be useful to you, not sure :)

Leonid Darovskikh

unread,
Oct 7, 2017, 6:09:30 AM10/7/17
to Haxe
Thanks, but that's not exactly what I'm looking for.

Leonid Darovskikh

unread,
Oct 7, 2017, 6:16:10 PM10/7/17
to Haxe
Ok, I understand now why it returned "Type name nrex.core.Dummy is redefined from module nrex.core.Dummy". That's because onAfterTyping callback is also called for the newly defined type.
Reply all
Reply to author
Forward
0 new messages