【问题标题】:How to return multiple values from a function in Kotlin like we do in Swift?如何像在 Swift 中一样从 Kotlin 中的函数返回多个值?
【发布时间】:2017-11-15 12:45:06
【问题描述】:

如何从 Kotlin 中的函数返回 3 个相同类型的单独数据值 (Int)?

我正在尝试返回一天中的时间,我需要将小时、分钟和秒作为单独的整数返回,但是从同一个函数中一次性返回,这可能吗?

我们会像下面这样快速地做,

func getTime() -> (Int, Int, Int) {
    ...
    return ( hour, minute, second)
}

我们可以在 Kotlin 中实现这一点吗?

P.S:我知道我可以为此使用 Array 或 Hashmap,但我想知道 Kotlin 中是否存在类似 Swift 的东西。

【问题讨论】:

标签: android kotlin


【解决方案1】:

您不能在 Kotlin 中创建任意元组,而是可以使用 data classes。一种选择是使用内置的PairTriple 类,它们是通用的,可以分别保存两个或三个值。您可以将这些与destructuring declarations 结合使用,如下所示:

fun getPair() = Pair(1, "foo")

val (num, str) = getPair()

您还可以解构ListArray,直到第一个5 elements

fun getList() = listOf(1, 2, 3, 4, 5)

val (a, b, c, d, e) = getList()

然而,最惯用的方法是定义您自己的数据类,它允许您从函数中返回一个有意义的类型:

data class Time(val hour: Int, val minute: Int, val second: Int)

fun getTime(): Time {
    ...
    return Time(hour, minute, second)
}

val (hour, minute, second) = getTime()

【讨论】:

    【解决方案2】:

    您似乎知道创建特定类来处理时间的明显答案。因此,我猜您正在尝试避免创建类或访问数组的每个元素等的小麻烦,并且正在寻找额外代码方面的最短解决方案。我建议:

    fun getTime(): Triple<Int, Int, Int> {
        ...
        return Triple( hour, minute, second)
    }
    

    并将其与解构一起使用:

    var (a, b, c) = getTime()
    

    如果您需要 4 或 5 个返回值(您不能解构超过 5 个),请使用 Array

    fun getTime(): Array<Int> {
        ...
        return arrayOf( hour, minute, second, milisec)
    }
    

    var (a, b, c, d) = getTime()
    

    P.S.:解构时你可以使用比值少的变量,比如var (a, b) = getTime(),但你不能使用更多,否则你会得到一个ArrayIndexOutOfBoundsException

    【讨论】:

      【解决方案3】:

      虽然通常一个函数只能返回一个值,但在 Kotlin 中,通过利用 Pair 类型和解构声明的优势,我们可以从一个函数返回两个变量。考虑以下示例:

      fun getUser():Pair<Int,String> {//(1) 
        return Pair(1,"Mahabub") 
      } 
      
      fun main(args: Array<String>) { 
        val (userID,userName) = getUser()//(2) 
        println("User ID: $userID t User Name: $userName") 
      } 
      

      来自:函数式 Kotlin 书

      【讨论】:

      • 出色的解决方案。
      【解决方案4】:

      使用 Triple 返回 3 个值,使用 Pair 返回 2 个值

      class Book(val title: String, val author: String, val year: Int) {
      
      
      fun getTitleAuthor(): Pair<String, String> {
          return (title to author)
      }
      
      fun getTitleAuthorYear(): Triple<String, String, Int> {
          return Triple(title, author, year)
      }}
      

      【讨论】:

        【解决方案5】:

        根据 Kotlin 文档 (https://kotlinlang.org/docs/reference/multi-declarations.html#example-returning-two-values-from-a-function),您可以这样实现:

        data class TimeData(val hour: Int, val minute: Int, val second: Int)
        
        fun getTime(): TimeData {
            // do your calculations
        
            return TimeData(hour, minute, second)
        }
        
        // Get the time.
        val (hour, minute, second) = getTime()
        

        【讨论】:

          【解决方案6】:

          您可以返回多个值,如下所示

          data class Result(val result: Int, val status: Status)
          fun function(...): Result {
              // computations
          
              return Result(result, status)
          }
          
          // Now, to use this function:
          val (result, status) = function(...)
          

          看到这个documentation

          更多示例见link

          【讨论】:

            【解决方案7】:

            Kotlin 中没有元组。或者,您可以将data classdestructuring declaration 一起使用。

            data class Time(val hour: Int, val minute: Int, val second: Int)
            
            func getTime(): Time {
                ...
                return Time(hour, minute, second)
            }
            
            //Usage
            val time = getTime()
            println("${time.hour}:${time.minute}:${time.second}")
            //Or
            val (hour, minute, second) = getTime()
            println("${hour}:${minute}:${second}")
            

            如果您不想为每个特定情况创建数据类,您可以创建一些通用数据类并使用typealias 以清楚起见。

            data class Two<A, B>(val a: A, val b: B)
            data class Three<A, B, C>(val a: A, val b: B, val c: C)
            data class Four<A, B, C, D>(val a: A, val b: B, val c: C, val d: D)
            ...
            
            typealias Time = Three<Int, Int, Int>
            

            但是,显然,缺点是您必须使用解构声明才能给它一个正确的属性名称。

            val time = getTime()
            println("${time.a}:${time.b}:${time.c}")
            
            val (hour, minute, second) = getTime()    //destructuring declaration
            println("${hour}:${minute}:${second}")
            

            【讨论】:

              【解决方案8】:

              如果您受到特殊限制并且希望在没有任何类分配的情况下返回多个值,您可能想要执行类似this

              val theBonus: Bonus
              val theStuff = getStuff { theBonus = it }
              
              doSomething(theStuff, theBonus)
              

              在哪里

              import kotlin.contracts.*
              
              @OptIn(ExperimentalContracts::class)
              inline fun getStuff(block: (Bonus) -> Unit): Stuff {
                  contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
                  val stuff = grabStuffFromCargoBikeBasket()
                  val bonus = inspirationElixir()
                  block(bonus)
                  return stuff
              }
              

              【讨论】:

                【解决方案9】:

                如果您想返回多个不同类型的值而不使用具有解构声明的类,您也可以为此使用Any 类型的List

                fun main() {
                    val (a, b, c) = getData()
                    println(a)
                    println(b)
                    println(c)
                }
                
                fun getData(): List<Any> {
                    val one = Int.MAX_VALUE
                    val two: List<Long> = listOf(1, 2, 3, 4)
                    val three: Pair<String, Char> = "a" to 'z'
                    return listOf(one, two, three)
                }
                

                这是输出:

                2147483647
                [1, 2, 3, 4]
                (a, z)
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-07-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-03-29
                  • 1970-01-01
                  相关资源
                  最近更新 更多