Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I generalize functions on an enum class in Kotlin?

How can I create a class which could be more reusable with enum classes, as I might have few more classes later on? My point is to make it more reusable, flexible and global for other usage.

enum class PaymentMethodType(val type: String) {

    PAYPAL("Paypal"),
    VISA("Visa"),
    MASTERCARD("MasterCard"),
    VISA_DEBIT("VISA Debit"),
    LPQ_CREDIT("Lpq Credit");

    companion object {

        private val TAG: String = this::class.java.simpleName

        fun fromString(name: String): PaymentMethodType? {
            return getEnumFromString(PaymentMethodType::class.java, name)
        }

        private inline fun <reified T : Enum<T>> getEnumFromString(c: Class<T>?, string: String?): T? {
            if (c != null && string != null) {
                try {
                    return enumValueOf<T>(
                        string.trim()
                            .toUpperCase(Locale.getDefault()).replace(" ", "_")
                    )
                } catch (e: IllegalArgumentException) {
                    Log.e(TAG, e.message)
                }
            }
            return null
        }
    }
}
like image 606
Jonas Simonaitis Avatar asked Sep 03 '25 17:09

Jonas Simonaitis


1 Answers

You can generalize your getEnumFromString function by creating an interface and having your companion object implementing it. An extension on this interface will let you call the function directly on the companion of your enum class.

This will do the trick:

interface EnumWithKey<T : Enum<T>, K> {
    val T.key: K
}

/* The reified type parameter lets you call the function without explicitly 
 * passing the Class-object.
 */
inline fun <reified T : Enum<T>, K> EnumWithKey<T, K>.getByKey(key: K): T? {
    return enumValues<T>().find { it.key == key }
}

Now you can create your PaymentMethodType like this:

enum class PaymentMethodType(val type: String) {
    PAYPAL("Paypal"),
    VISA("Visa"),
    MASTERCARD("MasterCard"),
    VISA_DEBIT("VISA Debit"),
    LPQ_CREDIT("Lpq Credit");

    companion object : EnumWithKey<PaymentMethodType, String> {
        // Just define what the key is
        override val PaymentMethodType.key
            get() = type
    }
}

And voila, now you can do this:

println(PaymentMethodType.getByKey("Paypal")) // Prints PAYPAL

The EnumWithKey interface can now be reused by just having the companion object of an enum implementing it.

like image 176
marstran Avatar answered Sep 07 '25 06:09

marstran