I want to create a generic class that holds the value of an enumeration, and also allows access to the possible values of the enumeration. Think of a property editor for example – you need to know the current value of the property, and you also need to be able to know what other values are legal for the property. And the type of enumeration should not be known in advance, you should be able to work with any kind of enumeration.
My first thought was something like this:
class EnumerationProperty[T <: Enumeration](value:T)
However, that doesn’t work because for enumerations T isn’t a type, it’s an object. Other variations I have tried are:
class EnumerationProperty[T <: Enumeration](value:T.Value)
class EnumerationProperty[T <: Enumeration.Value](value:T)
(I won’t go into the details of why these don’t work because I suspect the reasons aren’t interesting.)
In your use case (a property editor) I think the best solution is to rely on scala reflection available in scala 2.10. Given a class’s
TypeTag, you can get the full type (without erasure) of all of its members plus their values, and from that populate your property editor. For enumerations, use theTypeTagto get their values using the following method:Using Scala 2.10 reflection how can I list the values of Enumeration?
Now, maybe you don’t want or can’t use scala reflection, and from now on I’ll suppose this is the case. If that is true then you are opening a whole can of worm 🙂
TL;DR: This is not possible using a standard
Enumeration, so you’ll probably have to explcitly wrap the enumeration values as shown in Ptharien’s Flame’s answer (or roll your own fork ofEnumeration). Below I detail all my attempts, please bear with me.Unfortunately, and for some unknown reason to me (though I suspect it has to do with serialization issues),
Enumeration.Valuehas no field pointing to itsEnumerationinstance. Given howEnumerationis implemented, this would be trivial to implement, but of course wehave no say, short of forking Enumeration and modifying our version (which is actually what I did for this very purpose, plus to add proper support for serialization and reflection – but I diggress).If we can’t modify
Enumeration, maybe we can just extend it? Looking at the implementation again, something like this would seem to work:The downside would be that it only works for enumerations that explicitly extend
EnumerationExinstead ofEnumeration, but it would be better than nothing.Unfortunately, this does not compile simply because
def Value ...is declared final inEnumerationso there is no way to override it. (Note again that forkingEnumerationwould allow to circunvent this. Actually, why not do it, as we are already down the path of using a custom Enumeration anwyay. I’ll let you judge).So here is another take on it:
And indeed it works as expected. Or so it seems.
Hooray? Well no, because the conversion from
ValuetoValueWithEnumis done only when accessingred.enum, not at the time of instantiation of theColorsenumeration. In other words, when callingenumthe compiler needs to know the exact static type of the enumeration (the compiler must statically know that red’s type isColors.Value, and not justEnumeration# Value). And in the use case you mention (a property editor) you can only rely to java reflection (I already assumed that you won’t use scala reflection) to get the type of an enumeration value, and java reflection will only give youEnumeration#Val(which extendsEnumeration#Value) as the type ofColors.Red. So basically you are stuck here.Your best bet is definitly to use scala reflection in the first place.