首页 > 解决方案 > 如何在 Kotlin 的枚举类上泛化函数?

问题描述

我怎样才能创建一个可以通过枚举类更可重用的类,因为我以后可能会有更多的类?我的观点是让它更可重用、更灵活、更全球化,以供其他用途使用。

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
        }
    }
}

标签: androidkotlinenums

解决方案


您可以getEnumFromString通过创建接口并让伴随对象实现它来概括您的功能。此接口上的扩展将允许您直接在枚举类的伴侣上调用该函数。

这可以解决问题:

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 }
}

现在你可以PaymentMethodType像这样创建你的:

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
    }
}

瞧,现在你可以这样做了:

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

EnumWithKey现在可以通过让枚举的伴随对象实现它来重用该接口。


推荐阅读