简体   繁体   中英

How to make a generic function for enumValues<T> in Kotlin?

I struggle with providing a type as parameter for a procedure that uses the enumValues<MyEnum>() function. Got it to work with reified but using inline functions all the way is no option for me.

    fun <T: Enum<Trait>> traits(
        selectionState: SnapshotStateMap<Trait, Boolean>
    ) {
        val chunks = enumValues<T>().toList().chunked(5)
        chunks.forEach {
            Row {
                it.forEach {
                    TraitIcon(it, selectionState)
                }
            }
        }
    }

My enums all derive from enum class Trait . So in fact I want to pass enum class TraitFoo: Trait , enum class TraitBar: Trait and so on into the function.

Cannot use 'T' as reified type parameter. Use a class instead.

Is the compile error I receive here. Any idea of solving this? I am somewhat confused why this is not working.

Looking at the implementation of enumValues :

public inline fun <reified T : Enum<T>> enumValues(): Array<T>

I see it uses reified . That does mean the type has to be known at compile time. Therefore I can not pass a generic but need to pass an explicit type? Is that the issue?

If yes - is there another way to achieve this rather than using reified ?

If you want to be able to use T in your function as if it's a real type then it must be reified. And in order for a type parameter to be reified it must be part of an inline function. So you're going to need an inline function.

The next bit is figuring out the generics. You currently have:

<T : Enum<Trait>>

That means, due to the nature of enums, that T can't possibly be anything other than Trait . However, you have since clarified that Trait is not an enum but is actually an interface that's implemented by various enum classes. So what you really want is T to be bounded by both Enum<T> and Trait .

Given all this, I believe what you're looking for is the following:

inline fun <reified T> traits(
    selectionState: SnapshotTraitMap<Trait, Boolean>
) where T : Enum<T>, T : Trait {
    val chunks = enumValues<T>().toList().chunked(5)
    chunks.forEach {
        Row {
            it.forEach {
                TraitIcon(it, selectionState)
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM