代码之家  ›  专栏  ›  技术社区  ›  Crystal

检查或铸造从Kotlin Any到

  •  0
  • Crystal  · 技术社区  · 6 年前

    我试图构建一个函数,它需要 Map<String, Any>

    "key": 1 (int)
    "key": 1.2 (double)
    "key": "someString" (string)
    "key": [1, 2, 3] (array of ints)
    "key": ["apple", "banana", "cutie"] (array of strings)
    

    我想检查类型并将其强制转换为一个类型,这样就可以只使用单个值,也可以使用值数组。

    到目前为止,我可以做单一值:

    when (value) {
        is String -> doWork(value)
        is Int -> doWork(value)
        is Float -> doWork(value)
        is Double -> doWork(value)
        is IntArray -> ???
        else -> {
            // ???
        }
    }
    

    我对Kotlin很陌生,但是当我用

    foo(mapOf("test_track" to arrayOf(1, 2, 3))
    

    由于arrayOf返回一个 Array<Int> , Array<String> ,甚至 List<Int> Collection ,然后我可以使用 forEach 或者另一个循环/映射构造来获取单个元素。但我似乎找不到办法。

    1 回复  |  直到 6 年前
        1
  •  5
  •   Zoe - Save the data dump 张群峰    6 年前

    arrayOf 返回 Array<T> . 如果你想要一个完整的而不是一个 Array<Int> ,你在找 intArrayOf .

    IntArray is an int[] ,作为一个 阵列<T> 转换为整数[]。在这里你也许可以知道它失败的原因:一个 不是的实例 Integer[]

    观察到的类型Array和IntArray也是不同的,但是运行时的差异支持了它为什么会崩溃。

    Any . 这意味着您不能为这些对象执行具有多个类型的when分支。

    Any? 在这个过程中。

    // This function is just here to show what I've based this off (and make any misunderstandings visible early)
    fun processMap(map: Map <String, Any>) {
        for ((key, value) in map) {
            /*return value(s) = */
            processValue(value);
        }
    }
    
    fun processValue(value: Any?) {
        when (value) {
            // ... other types. I'm going to assume doWork acts differently based on types, but
            // if it is the same function and there are no type differences, you can
            // merge them into a single branch with:
            //
            // is String, is Int, is Float, is Double -> doWork(value)
            // ...
            is String -> doWork(value)
            is Int -> doWork(value)
            is Float -> doWork(value)
            is Double -> doWork(value)
            // ...
            // Process lists, collections, and other Iterables. 
            is Iterable<*> -> value.forEach { processValue(it) }
            // Process Arrays
            is Array<*> -> value.forEach { processValue(it) }
            // Process primitive arrays
            is IntArray -> value.forEach { processValue(it) }
            is FloatArray -> value.forEach { processValue(it) }
            // And so on
    
        }
    }
    

    如果您计划处理地图,可以使用 is Map<*, *>

    Array , ,和 FloatArray 就是让聪明的演员发挥作用。如果将它们连接到一个分支中,它会断开,因为它无法确定类型。这意味着你要回到 任何 ,它不会自动具有 iterator() 方法,它可以防止两者同时发生 value.forEach for(item in value) . 缺少 杂乱无章 ,

    但这两种方法都产生相同的实例,因此,也就是说。 Array<Int>.forEach IntArray.forEach 都会触发 is Int 你的when语句的分支。

        2
  •  3
  •   Wietbot    6 年前

    您可以做的是迭代Iterable的元素并处理这些元素。

    fun doAction(value: Any?)
    {
        when (value)
        {
            is Iterable<*> -> {
                value.forEach {
                    doAction(it)
                }
            }
        }
    }
    

    这意味着您不能真正对Array执行特殊操作,但可以处理它的所有元素。