Kotlin – 我如何从我的方法返回不同的types?
我有这个方法。
private fun getOffer(offers: OfferRepresentation, type: OfferType): ???? { return when (type) { OfferType.ADDON -> offers.addon OfferType.SALE -> offers.sale OfferType.PLAN -> offers.plan OfferType.CUSTOMPLAN -> offers.customPlan }
我怎样才能改变这种方法来返回正确的types?
如果不提供更多信息,很难给出一个二元的答案,但返回多种types的最简单的方法是让它们共享一个接口或超类:
interface Offer class Addon : Offer class Sale : Offer class Plan : Offer class CustomPlan : Offer
如果您的选项是静态的,您也可以使用sealed class
,这取决于您的使用情况。 无论哪种方式,您可以只有函数返回types是Offer
有关更多信息,请参阅
- 接口
- 密封类
以下是你如何做到这一点:
object Main { // concrete class for all "enum" values (such as OfferType.ADDON or OfferType.SALE) // that get passed to `getOffer` as second param class OfferType { companion object Types { // "enum" values. Unfortunately Kotlin doesn't support // type parameters for real enums @JvmStatic val ADDON = OfferType() @JvmStatic val SALE = OfferType() data class Addon(val name: String) data class Sale(val name: String) } } data class OfferRepresentation( val addon: OfferType.Types.Addon, val sale: OfferType.Types.Sale ) @JvmStatic fun main(args: Array) { fun getOffer(offers: OfferRepresentation, type: OfferType ): T { @Suppress("UNCHECKED_CAST") return when (type) { OfferType.ADDON -> offers.addon as T OfferType.SALE -> offers.sale as T else -> throw IllegalArgumentException("Unsupported type $type") } } val offer = OfferRepresentation( OfferType.Types.Addon("addon"), OfferType.Types.Sale("sale") ) // types are specified explicitly for the sake of demonstration val addon: OfferType.Types.Addon = getOffer(offer, OfferType.ADDON) val sale: OfferType.Types.Sale = getOffer(offer, OfferType.SALE) println("$addon, $sale") } }
请注意, getOffer
函数中有一个UNCHECKED_CAST
。 您有责任确保OfferType.ADDON
( OfferType.SALE
等)值使用正确的OfferRepresentation
的字段types进行参数化,并且逻辑也是正确的,否则将在运行时得到ClassCast
exception。
UPD 。 有一个替代的实现,使用了一点kotlin魔术,具体来说, 物化types 。 通过这种方法,您可以不使用单独的实体来定义要从getOffer
函数返回的字段,而只需指定显式types参数。 另外,你可以依靠隐式types推断:
object Main2 { object OfferType { data class Addon(val name: String) data class Sale(val name: String) } data class OfferRepresentation( val addon: OfferType.Addon, val sale: OfferType.Sale ) //reified type parameters require function to be inline inline fun getOffer(offers: OfferRepresentation): T { @Suppress("UNCHECKED_CAST") return when (T::class) { OfferType.Addon::class -> offers.addon as T OfferType.Sale::class -> offers.sale as T else -> throw IllegalArgumentException("Unsupported type ${T::class}") } } @JvmStatic fun main(args: Array) { val offer = OfferRepresentation( OfferType.Addon("addon"), OfferType.Sale("sale") ) // types needed to be specified explicitly here val addon: OfferType.Addon = getOffer(offer) val sale: OfferType.Sale = getOffer(offer) // alternatively `getOffer` should be invoked like this: getOffer(offer) println("$addon, $sale") } }
你有使用Any
作为你的返回types的微不足道的解决方案。 Any
都不完全像Java中的Object
,但在这种情况下足够接近( https://kotlinlang.org/docs/reference/classes.html ):
Kotlin中的所有类都有一个公共的超类Any ,这是一个没有声明超类的类的默认超类:
class Example // Implicitly inherits from Any
所以如果你的返回types是完全不相关的,并且让你共享一个通用接口是没有意义的,那么你可以使用Any:
private fun getOffer(offers: OfferRepresentation, type: OfferType): Any { return when (type) { OfferType.ADDON -> offers.addon OfferType.SALE -> offers.sale OfferType.PLAN -> offers.plan OfferType.CUSTOMPLAN -> offers.customPlan }
您不能从JVM的函数返回多个值。 你可以做的是返回一个Pair或Tuple或创建一个Data类的所有领域,然后把它们作为可选项
例如:
数据类提供(val type1:String?= null,val type2:Integer?= 0)