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