Maxime Michel
Maxime Michel

Reputation: 615

Generic Enum type parameter with required interface

I have an interface that looks like the following:

interface LabelledEnum {
    fun getLabelId(): Int
}

I inherit this interface in an enum class as follows:

enum class Period : LabelledEnum {
    YTD {
        override fun getLabelId(): Int =
            R.string.ytd_label
    },
    ONE_MONTH {
        override fun getLabelId(): Int =
            R.string.1m_label
    },
    THREE_MONTHS {
        override fun getLabelId(): Int =
            R.string.3m_label
    },
    SIX_MONTHS {
        override fun getLabelId(): Int =
            R.string.6m_label
    },
    ONE_YEAR {
        override fun getLabelId(): Int =
            R.string.1y_label
    },
    THREE_YEARS {
        override fun getLabelId(): Int =
            R.string.3y_label
    },
    FIVE_YEARS {
        override fun getLabelId(): Int =
            R.string.5y_label
    },
    MAX {
        override fun getLabelId(): Int =
            R.string.max_label
    };
}

I have a custom composable I am working on where I want to make it generic (use type parameters instead of hardcoding things) but I am struggling to find a way to implement this generic type parameter such that the type parameter is necessarily an Enum that inherits my interface LabelledEnum.

So far, my composable looks like this:

@Composable
inline fun <reified T : Enum<T>> CustomTabRow(
    selectedEnum: T,
    crossinline onEnumSelected: (T) -> Unit,
    modifier: Modifier = Modifier,
) {
    // Things happen here
}

Is there a way to ensure that the type parameter T is an Enum AND inherits from LabelledEnum ?

If not, I'll use a workaround but I'd really prefer to make this work if at all possible

Upvotes: 1

Views: 393

Answers (1)

Todd
Todd

Reputation: 31720

Kotlin has a where syntax to express constraints like this.

@Composable
inline fun <reified T> CustomTabRow(
    selectedEnum: T,
    crossinline onEnumSelected: (T) -> Unit,
    modifier: Modifier = Modifier,
) where T : Enum<T>, T : LabelledEnum  {
    // Things happen here
}

Note that you have to move T : Enum<T> to the where clause.

Upvotes: 4

Related Questions