Есть ли способ указать несколько возможных типов для аргумента функции в Kotlin?

Рейтинг: 2Ответов: 1Опубликовано: 18.05.2023

Я пишу тест для API метода, который может принимать несколько типов данных, но, понятное дело, не все. Мне бы хотелось найти возможность передавать в функцию один из возможных типов в духе String or Int.

Знаю возможные варианты решения, но мне они не нравятся:

  1. Использовать тип Any - небезопасно и как-то не очень вообще.
  2. Повторно объявить функцию, где будет указан уже другой тип аргумента - невозможно, некоторые методы принимают множество подобных аргументов. Я так понимаю, что так придется делать для каждой комбинации разных типов?

Пример минимально воспроизводимого кода:

fun main() {
    
    fun myRequestMethod(
        firstParam: Any, //actualy can be ONLY String or Int
        secondParam: Any, //actualy can be ONLY String or Int
        thirdParam: Any //actualy can be ONLY String or Int
    ) {
        //do api-request
        println("$firstParam, $secondParam, $thirdParam")
    }
    
    myRequestMethod(1, 2, 3) //acceptible with Any type
    myRequestMethod("1", 2, "3") //acceptible with Any type
    myRequestMethod(mapOf("1" to 1), listOf(2, 2, 2), "3") //NOT acceptible with Any type
    myRequestMethod(1, listOf(1, 2, 3), mapOf("1" to 1)) //NOT acceptible with Any type
}

Может есть какое-то решение, которое я не смог найти? Спасибо!

Ответы

▲ 1Принят

Именно так, как вы хотите, сделать нельзя, но можно сделать sealed-класс с двумя реализациями:

sealed class Param

class IntParam(val value: Int) : Param()

class StringParam(val value: String) : Param()

И пару экстеншенов для удобства:

val Int.param get() = IntParam(this)

val String.param get() = StringParam(this)

Вместо Any теперь можно использовать Param, а вызывать метод можно будет следующим образом:

myRequestMethod(1.param, 2.param, 3.param)
myRequestMethod("1".param, 2.param, "3".param)

Конечно, это не совсем то, что вы хотели, но я попытался максимально приблизить к тому, что требовалось.

Кроме этого, в sealed-класс можно добавить какой-нибудь абстрактный метод, в зависимости от того, как вы дальше планируете работать с этими параметрами в коде.