COMMUNITY

Nested enums and/or classes


(Kyliathy) #1

I’m trying to translate the following nested structure of Strings (and potentially Ints) into type-safe code that can also be easily type-hinted and refactored via an IDE (so this rules out anonymous structures) , but in the same time must be interpretable at run-time without reflection (which would incur a performance hit upon heavy use, and I do intend some very heavy use of the data below).

In C# or Java I could easily achieve this using nested classes.

My purpose is to allow somebody to drill down through an ever-more-specific categorized hierarchy. The values in the hierarchy must be printable on the screen (without using reflection or “switch” statements), so of course I was thinking about String variables.

Material: "Material"
- Scratched: "Scratched"
--- Damaged: "Damaged"
- Shiny: "Shiny"
--- Polished: "Polished"
----- Reflective: "Reflective"
--- Finished: "Finished"

It could work with enums I guess if only they would allow members to be String values. They could, if I use Switch, but I want to print enum members without resorting to Switch statements.

I also tried @:enum abstract, but I’m kinda stuck with compile errors. For example I tried:

@:enum
abstract Materials (String)
{
	public var name: String = "Materials";
	public var ShinyChild: Shiny;
	public var Scratched: String = "Scratched";
}

@enum
abstract Shiny (String)
{
	var name: String = "Shiny";
	var Polished: String = "Polished";
	var Finished: String = "Finished";
}

I also tried static classes.

class Materials
{
	public static var name: String = "Materials";
	public static var ShinyChild: Shiny;
	public static var Scratched: String = "Scratched";
}

class Shiny
{
	public static var name: String = "Shiny";
	public static var Polished: String = "Polished";
	public static var Finished: String = "Finished";
}

This of course doesn’t work because in Materials.ShinyChild.name ShinyChild is instantiated.


(Kyliathy) #3

I can do this if I instantiate the hierarchy parent class once. That’s not exactly ideal.

class Materials
{
	public var name: String = "Materials";
	public var child: Shiny = new Shiny();
	public var Scratched: String = "Scratched";
	public function new () {}
}

class Shiny
{
	public var name: String = "Shiny";
	public var Polished: String = "Polished";
	public var Finished: String = "Finished";
	public function new () {}
}
var mat: Materials = new Materials();
w(mat.child.Polished); //Prints "Polished" as desired.

I tried singleton, doesn’t work yet.


(Kyliathy) #4

Ok, I managed to create this Frankenstein so you can all have a laugh.

class CollectionBase
{
	public var name: String = "None";

	public function new (v: String)
	{ if (v != null) name = v; }

	public function toString(): String	{ return name; }
}

class Materials extends CollectionBase
{
	public var ShinyC: Shiny = new Shiny("Shiny");
	public var Scratched: CollectionBase = new CollectionBase("Scratched");

	public static var instance(default, null):Materials = new Materials("Materials");
	private function new (v: String) { super(v); }
}

class Shiny extends CollectionBase
{
	public var PolishedC: Polished = new Polished("Polished");
	public var Finished: CollectionBase = new CollectionBase("Finished");

	public function new (v: String)	{ super(v); }
}

class Polished extends CollectionBase
{
	public var Reflective: CollectionBase = new CollectionBase("Reflective");

	public function new (v: String)	{ super(v); }
}

This achieves the goal and also encapsulates a collection inside a singleton.


(Dan Korostelev) #5

This looks a bit like an XY problem to me as I am not sure what’s the actual intent here. Really just a set of string values grouped in a hierarchy? And if so, why not anonymous structures? Their performance depend on a target, but if you use JS it will be as fast as any other object. And you can give them names using a typedef for easy type hinting and navigation. Otherwise, your solution with class instances isn’t that bad too :slight_smile:


(Kyliathy) #6

It’s not XY problem, it’s just perhaps so ridiculously simple that I overlooked it. I’ve also taken quite a long break from serious coding in the past years so please forgive my silliness :).

typedef? Hm. I didn’t check it out, but my goal is also to allow easy renaming of values throughout the project using refactor. And I need type-safety because if somebody messes with the structure the project needs to fail compiling.

I’m gonna check typedef in more depth tomorrow. I would indeed like an anonymous structure, as long as it satisfies the above requirements. Not familiar with how typedef works in Haxe but what I’ve read now is reassuring.


(Mark) #7

With anonymous structure it would look like:
https://try.haxe.org/#ED933

If you want the typing for that, just use $type(data), then you can use this as typedef:
https://try.haxe.org/#68387


As alternative, If you would use enums then the structure could look like this:
https://try.haxe.org/#D5791
But it depends on use case if its useful or not. It can be nice if the structure is more complex and you want to use pattern matching.


(Kyliathy) #8

Aaah, so THAT’s how nested typedefs can be created :smiley:. I was just now following up on @nadako’s comment trying to figure out how to setup a nested typdef. Nice! Thank you guys! :slight_smile:


(Mark) #9

Well you can do it by hand of course, but doing so basically you let the compiler figure out, and use that :stuck_out_tongue:


(Kevin Leung) #10

typedef merely means alias. It is not the name of the type you guys are mentioning. A more correct name would be anonymous structure.