¿Cómo puedo crear una clase que podría ser más reutilizable con las clases de enumeración, ya que podría tener algunas clases más más adelante? Mi punto es hacerlo más reutilizable, flexible y global para otros usos.
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 } } }Puede generalizar su función getEnumFromString creando una interfaz y haciendo que su objeto complementario la implemente. Una extensión en esta interfaz le permitirá llamar a la función directamente en el complemento de su clase de enumeración.
Esto hará el truco:
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 } } Ahora puede crear su PaymentMethodType de esta manera:
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 } }Y listo, ahora puedes hacer esto:
println(PaymentMethodType.getByKey("Paypal")) // Prints PAYPAL La interfaz EnumWithKey ahora se puede reutilizar con solo implementar el objeto complementario de una enumeración.
¿Bien? ¿Qué tal este código?
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 = PaymentMethodType::class.simpleName fun fromString(name: String?): PaymentMethodType? { val maybeType = PaymentMethodType.values().firstOrNull { it.type == name } if (maybeType == null) { Log.e(TAG, "No corresponding PaymentMethodType for $name") } return maybeType } } } Acabo de simplificar el método getEnumFromString de esta manera.
Además, si desea que su PaymentMethodType sea más "reutilizable, flexible y global", agregue algún método abstracto a su PaymentMethodType o considere usar la clase Sealed en este caso. Podemos adivinar que muchos métodos de pago requieren sus propios protocolos, y su implementación mediante enum requiere una rama externalizada when o if-else para hacerlo. Por ejemplo, el código debería verse así:
fun paymentProcessor(payment: PaymentMethodType): Boolean { return when (payment) { PAYPAL -> { processPaypalPayment() } VISA -> { processVisaPayment() } // ... } } lo cual no está mal a menos que la cantidad de métodos de pago sea limitada pero no del todo deseable. Podemos eliminar esta palabra clave insidiosa if o when de esta manera (manteniendo el enfoque enum class ):
enum class PaymentMethodType(val type: String) { PAYPAL("Paypal") { override fun processPayment(): Boolean { TODO("Not implemented.") } }, VISA("Visa") { override fun processPayment(): Boolean { TODO("Not implemented.") } }, // ... more types ... ; abstract fun processPayment(): Boolean // ... } Con cualquiera de los enfoques, podemos eliminar when la palabra clave en el método paymentProcessor lo demostré así:
fun paymentProcessor(payment: PaymentMethodType): Boolean { return payment.processPayment() } No explico el enfoque sealed class ya que el código no es muy diferente en comparación con el enfoque de enum class en este caso. El documento oficial puede ayudar.
Espero que esto ayude.
Obtenga todos los valores de enumeración con PaymentMethodType.values() , luego use find() para obtener el que necesita:
fun fromString(type: String): PaymentMethodType? = PaymentMethodType.values().find { it.type.toLowerCase() == type.toLowerCase() }