Kotlin – Как я могу вернуть разные типы из моего метода?

У меня есть этот метод.

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 } 

Как я могу изменить этот метод, чтобы вернуть правильный тип?

Трудно дать вам простой ответ, если вы не указали больше информации, но самый простой способ вернуть несколько типов – это предоставить им общий доступ к интерфейсу или суперклассу:

 interface Offer class Addon : Offer class Sale : Offer class Plan : Offer class CustomPlan : Offer 

Вы также можете использовать sealed class если ваши параметры статичны, это зависит только от вашего прецедента. В любом случае, вы можете просто использовать функцию return type 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<T> { companion object Types { // "enum" values. Unfortunately Kotlin doesn't support // type parameters for real enums @JvmStatic val ADDON = OfferType<Addon>() @JvmStatic val SALE = OfferType<Sale>() 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<String>) { fun <T> getOffer(offers: OfferRepresentation, type: OfferType<T>): 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") } } 

Обратите внимание, что в функции UNCHECKED_CAST getOffer . Вы OfferType.ADDON ответственность за то, чтобы значения OfferType.ADDON ( OfferType.SALE и т. Д.) OfferType.SALE параметризованы с правильным OfferRepresentation поля OfferRepresentation а также при правильной логике, иначе вы получите исключение ClassCast во время выполнения.


UPD . Существует альтернативная реализация, которая использует немного магии kotlin, в частности, типы reified. При таком подходе вместо наличия отдельных объектов для определения поля, которое вы хотите вернуть из функции getOffer вы просто указываете явный параметр типа. В качестве альтернативы вы можете полагаться на неявный тип вывода:

 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 <reified T> 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<String>) { 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<OfferType.Addon>(offer) println("$addon, $sale") } } 

У вас есть тривиальное решение использовать Any качестве возвращаемого типа. Any Object не похож на Object в Java, но в этом случае он достаточно близко ( https://kotlinlang.org/docs/reference/classes.html ):

Все классы в Kotlin имеют общий суперкласс All, который является суперполе по умолчанию для класса без объявленных супертипов:

 class Example // Implicitly inherits from Any 

Поэтому, если ваши типы возврата полностью не связаны между собой, и вам не имеет смысла, чтобы они делили общий интерфейс, тогда вы можете использовать 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. Что вы можете сделать, это вернуть пару или кортеж или создать класс данных со всеми полями, а затем использовать их как необязательные

Например:

класс данных Предложение (val type1: String? = null, val type2: Integer? = 0)