如何创建一个可以在枚举类中重用的类,因为以后可能还会有几个类?我的观点是使它更可重用,灵活并且在其他用途上具有全局性。
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
}
}
}
答案 0 :(得分:1)
您可以通过创建接口并让您的伴侣对象实现该接口来概括您的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
接口现在可以重新使用,只需让枚举的同伴对象实现即可。
答案 1 :(得分:1)
使用PaymentMethodType.values()
获取所有枚举值,然后使用find()
获得所需的枚举值:
fun fromString(type: String): PaymentMethodType? = PaymentMethodType.values().find { it.type.toLowerCase() == type.toLowerCase() }
答案 2 :(得分:0)
好吗?这个代码怎么样?
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
}
}
}
就像这样简化getEnumFromString
方法。
此外,如果您想使PaymentMethodType更具“可重用性,灵活性和全局性”,请在您的PaymentMethodType
上添加一些抽象方法,或者在这种情况下考虑使用 Sealed类。我们可以猜测,许多付款方式都需要自己的协议,而通过enum
实现它需要外部化的when
或if-else
分支来做到这一点。例如,代码应如下所示:
fun paymentProcessor(payment: PaymentMethodType): Boolean {
return when (payment) {
PAYPAL -> { processPaypalPayment() }
VISA -> { processVisaPayment() }
// ...
}
}
这很不错,除非付款方式的数量受到限制,但并不是很理想。我们可以像这样删除这个阴险的if
或when
关键字(保留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
// ...
}
无论采用哪种方法,我们都可以在我演示过的when
方法中消除paymentProcessor
关键字:
fun paymentProcessor(payment: PaymentMethodType): Boolean {
return payment.processPayment()
}
我不解释sealed class
方法,因为在这种情况下,代码与enum class
方法相比并没有太大不同。 The official document可能会有帮助。
希望这会有所帮助。