Kotlin 的"映射"如何以及为什么是可迭代的,即使它不是"可迭代的"?



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

来自标准库源代码:

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循环是由约定:

定义的

Kotlin中的一些语法形式是由约定

定义的,这意味着它们的语义是通过从一种语法形式扩展到另一种语法形式来定义的。

对于for(VarDecl in C) Body,展开后的语法形式为:

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

不需要特定的接口,只需要重载解析为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() = ""
}

在您的示例中,存在Map的扩展函数iterator:

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

andMutableMap:

@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扩展函数:)

相关内容

  • 没有找到相关文章

最新更新