Classes as enums in D?

Meta via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Nov 30 00:08:18 PST 2015


On Monday, 30 November 2015 at 07:48:37 UTC, Andrew LaChance 
wrote:
> Hello,
> D has intrigued me for a while, and I thought I would finally 
> read up on it!  I've been reading "Programming in D" by Ali 
> Çehreli and I've been thinking about how I can use the language 
> in a side project I'm working on, porting it from java to D.  
> One of the uncommonly-used features of java that I like is how 
> enums can be full classes (though I don't like that there's no 
> option to use enums as e.g. regular ints).  This allows several 
> benefits, such as the ability to use them in switch statements 
> like regular enums, the full set of objects is known at compile 
> time, all objects are immutable, it's impossible to 
> accidentally or purposefully create new objects of that type, 
> etc...
>
> For example (in java), if I wanted to have an enum that 
> describes all the white keys on a piano keyboard and have 
> members that describe the number of half-steps to the next 
> white key and to the previous white key, I can define an enum 
> (the "id" or enum value is implicitly defined so it doesn't 
> have to be explicitly written in the definition):
>
> enum WhiteKey
> {
>     A(2,2),
>     B(2,1),
>     C(1,2),
>     D(2,2),
>     E(2,1),
>     F(1,2),
>     G(2,2);
>
>     private final int halfStepsToNext;
>     private final int halfStepsToPrevious;
>
>     WhiteKey(int halfStepsPrevious, int halfStepsNext)
>     {
>         this.halfStepsToPrevious = halfStepsPrevious;
>         this.halfStepsToNext = halfStepsNext;
>     }
> }
>
> From what I've read and seen, in D all enums have forced to 
> integral types.  Is it possible to do the above in D and I have 
> just missed it?  I can think of a few ways around it (such as 
> statically create and define a bunch of WhiteKey structs, ...), 
> but none are as clean as the above.  If this isn't something 
> supported, is it on a roadmap of wanted features?
>
> Thanks!  I'm looking forward to really getting to know the 
> language.

Yes and no. You can use arbitrary types for enums in D but a lot 
of the time you shouldn't when it involves types that are not 
Plain Old Data. A naive translation would be like this:

class WhiteKey
{
	private immutable int halfStepsToNext;
	private immutable int halfStepsToPrevious;

	enum
	{
		A = new WhiteKey(2, 2),
		B = new WhiteKey(2, 1),
		C = new WhiteKey(1, 2),
		D = new WhiteKey(2, 2),
		E = new WhiteKey(2, 1),
		F = new WhiteKey(1, 2),
		G = new WhiteKey(2, 2),
	}
	
	private this(int halfStepsToPrevious, int halfStepsToNext)
	{
		this.halfStepsToPrevious = halfStepsToPrevious;
		this.halfStepsToNext = halfStepsToNext;
	}
}

However, you do NOT want to do this, as everywhere you use 
WhiteKey's members, a new object will be created. For example:

auto f = WhiteKey.A;
auto n = WhiteKey.A;
	
import std.stdio;
writeln(&f, " ", &n);

This will two different addresses, because a new object is being 
created each time. It's basically taking the expression `new 
Key(2, 2)` and copy-pasting it wherever you use WhiteKey.A. 
Java's enums are basically syntax sugar for this:

class WhiteKey
{
	private immutable int halfStepsToNext;
	private immutable int halfStepsToPrevious;

	public static WhiteKey A = new WhiteKey(2, 2);
	public static WhiteKey B = new WhiteKey(2, 1);
	public static WhiteKey C = new WhiteKey(1, 2);
	public static WhiteKey D = new WhiteKey(2, 2);
	public static WhiteKey E = new WhiteKey(2, 1);
	public static WhiteKey F = new WhiteKey(1, 2);
	public static WhiteKey G = new WhiteKey(2, 2);
	
	private this(int halfStepsToPrevious, int halfStepsToNext)
	{
		this.halfStepsToPrevious = halfStepsToPrevious;
		this.halfStepsToNext = halfStepsToNext;
	}
}

This doesn't quite work in D; you'd have to make each WhiteKey 
const (which is probably not a bad idea anyway if you're using it 
like an enum). However, it's better to just do this with plain 
old value-type structs. It's exactly the same as my previous code 
defining a WhiteKey class with an embedded enum, but using a 
struct instead of a class.



More information about the Digitalmars-d-learn mailing list