Enum class with type parameters

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?

3 Likes

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?

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.

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)
}
2 Likes

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?

1 Like

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.

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…

2 Likes

No news on this? It still bugs me regularly…

This subject seems related to JEP 301: Enhanced Enums proposal.

Right, you don’t have ordinals like in enums, but it is possible to iterate sealed objects:

private sealed class SealedValue {
	object A : SealedValue()
	object B : SealedValue()
	object C : SealedValue()
}

fun main() {
	val sealedValues = SealedValue::class.sealedSubclasses.mapNotNull { it.objectInstance }
	sealedValues.forEach(::println)
}
1 Like

To have a logically related iterable set of objects (without having to use reflection) I just wrote the following helper base class:

open class EnumObjectList<T> private constructor( private val list: MutableList<T> ) :
    List<T> by list
{
    constructor() : this( mutableListOf() )

    protected fun <TAdd : T> add( item: TAdd ): TAdd = item.also { list.add( it ) }
}

Which for example can be used as follows:

object SamplingSchemes : EnumObjectList<DataTypeSamplingScheme<*>>()
{
    val GEOLOCATION = add( Geolocation( TimeSpan.fromMinutes( 1.0 ) ) )
    val STEPCOUNT = add( Stepcount( TimeSpan.fromMinutes( 1.0 ) ) )
}

The members retain their full type information, and there is no need for an ‘intermediate’ enum type.

1 Like

I wrote the full reasoning behind this up in a blog post: https://whatheco.de/2020/05/05/list-of-strongly-typed-objects-acting-like-enum-in-kotlin/

1 Like