Enum class with type parameters


#1

Kotlin currently does not support type parameters on enums, but it would be useful to have them.

There has been some discussion here from people missing the same feature in Java:

Could this be possible in Kotlin?


#2

Do you have a good use-case?

The problem I see is that if you manipulate an enum member through the enum type, you can’t access the type parameter.

So you only get access to it when you manipulate the enum member by name. But then you can “harcode” the parameter everywhere it is used.

That leaves extending a generic class with different parameters for different enum members. That is indeed Lukas’ exemple:

public interface DataType<T> {}

public enum SQLDataType<T> implements DataType<T> {
    TINYINT<Byte>,
    SMALLINT<Short>,
    INT<Integer>,
    BIGINT<Long>,
    CLOB<String>,
    VARCHAR<String>,
    ...
}

But that’s only the definition. How to use that usefully?


#3

I’d say SQLDataType is a very good use-case example, as it is directly from jOOQ.

An example of how that is useful: in jOOQ, a query result object has the following method:

<T> Field<T> field(String name, DataType<T> dataType)

So you could use result.field("name", SQLDataType.VARCHAR) to actually get a string,
or result.field("id", SQLDataType.INT) to get an int, etc.


#4

Maybe it’s better to use sealed class hierarchy in such case?

sealed class SQLDataType<T : Any>(val datatype: KClass<T>) {
    object TINYINT : SQLDataType<Byte>(Byte::class)
    object SMALLINT : SQLDataType<Short>(Short::class)
    // etc
    object VARCHAR : SQLDataType<String>(String::class)
}

#5

That would be better than using normal class hierarchy, but I think sealed classes are not really suitable if you just need a fixed set of objects. For example, with sealed classes you can’t iterate all its objects, or get an object’s ordinal.

Enums would be perfect for these cases, but for some unknown reason Java and Kotlin do not allow type parameters on them. Could it be done, or is there a reason it’s not possible?


#6

I know it’d be tedious to implement for a lot of instances, but you could add an iterative accessor, ordinal accessor, and some other stuff (i.e. valueOf or something) manually. Not a great solution of course, but it could serve as a workaround at least.


#7

I REALLY WANT THIS!!

consider this enum:

enum class Conjunction(private val pred: (Predicate<Any>, Predicate<Any>) -> Predicate<*>) : (Predicate<Any>, Predicate<Any>) -> Predicate<*> 
{
    AND({ p1, p2 -> p1.and(p2) }),
    OR({ p1, p2 -> p1.or(p2) });
    override fun invoke(p1: Predicate<Any>, p2: Predicate<Any>) = pred(p1, p2)
}

Absence of type parameters makes it basically unusable. Could I use type Parameters, then I would replace Any with T, but I can’t, so I have to resort to a normal class now…