就像在 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
}
最后,是否有可能制作支持這種語法的自定義類?如果是這樣,怎么做?
uj5u.com熱心網友回復:
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>
}
如規范中所述。
不需要特定介面,只需要多載決議operator為iterator()和找到適當hasNext()的多載next()。作為一個極端的例子,這個編譯!
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() = ""
}
在您的情況下,存在一個擴展iterator功能Map:
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 回圈就可以作業。這同樣適用于next和hasNext。
因此,要使您自己的類使用 for 回圈,您需要的最低限度是宣告:
operator fun iterator(): Iterator<Something>
但是我仍然建議您實作Iterable,因為這樣您就Iterable可以免費獲得所有擴展功能:)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/486713.html
