正如在Java中一样,任何Iterable的对象都可以在增强的for循环中使用.我认为Kotlin 也是如此,直到我发现kotlin.collections.Map根本不是Iterable.

from the standard library source code:

public interface Map<K, out V> {
    // ....

如果没有,那么这样的事情怎么可能呢

val map: Map<String, Int> = HashMap()
// ...
for ((s, i) in map) {
    println(s)
    println(i)
    // works perfectly
}

最后,是否可以创建支持此语法的自定义类?如果是,如何?

推荐答案

Kotlin for循环为defined by convention:

Kotlin中的一些语法形式是defined by convention,这意味着它们的语义是通过将一种语法形式扩展为另一种语法形式来定义的.

对于for(VarDecl in C) Body,它扩展到的语法形式是:

when(val $iterator = C.iterator()) {
    else -> while ($iterator.hasNext()) {
                val VarDecl = $iterator.next()
                <... all the statements from Body>
            }

按规定here in the spec.

不需要特定的接口,只需要重载解析为iterator()hasNext()next()找到适当的operator个重载.作为一个极端的例子,这个编译!

fun main() {
    for (s in Foo()) { // no error here!
        
    }
}

class Foo {
    operator fun iterator(): Bar = Bar()
}

class Bar {
    operator fun hasNext() = false
    operator fun next() = ""
}

在您的情况下,有exists个用于Map的扩展函数iterator:

operator fun <K, V> Map<out K, V>.iterator(): Iterator<Entry<K, V>>

MutableMap:

@JvmName("mutableIterator") 
operator fun <K, V> MutableMap<K, V>.iterator(): MutableIterator<MutableEntry<K, V>>

iterator方法不必在Map中声明-只要重载解析可以解决它,for循环就可以工作.这同样适用于nexthasNext.

因此,要使您自己的类使用for循环,您至少需要声明:

operator fun iterator(): Iterator<Something>

但我仍然建议您实现Iterable,因为这样您就可以免费获得所有Iterable个扩展函数:)

Kotlin相关问答推荐

最好的方法来创建一个 map 在kotlin从两个列表

Kotlin和JavaFX:绑定行为奇怪

Kotlin:将泛型添加到列表任何>

Kotlin-elvis算子don';不使用map.get()

如何使用multiset与JOOQ获取关联的记录列表?

如何在 Jetpack Compose 中启动和停止动画

jlink:在合并模块和 kotlin.stdlib 中打包 kotlin.*

在 Kotlin 中,为什么在 `+` 之前但在 `.` 之前没有换行符?

如何在 kotlin 中使用带有泛型的密封类

Kotlin spring boot @RequestBody 验证未触发

有没有办法重用 Job 实例?

比较 Kotlin 中的可比对象列表

Map.mapTo 到另一个map

Kotlinwhen表达式在使用主题时是否支持复合布尔表达式?

什么是开放式property?为什么我不能将其设置器设为private私有?

Kotlin-通过与属性列表进行比较来筛选对象列表

Kotlin 扩展函数 - 覆盖现有方法

uses-sdk:minSdkVersion 16 不能小于库中声明的版本 23

Android Studio - java.io.IOException:无法生成 v1 签名

Kotlin中对象和数据类的区别是什么?