我对operator fun iterator()
和Iterable
接口之间的分隔感到困惑。 Iterable
唯一需要的功能是operator fun iterator()
,它已经内置在语言中。我不知道为什么在任何情况下都可以实现operator fun iterator()
而不是Iterable
接口。这就引出了一个问题:为什么不用实现相应的接口就可以使某些事情变得可迭代?这样做似乎是错误的。同样,operator fun next()
和operator fun hasNext()
是否不总是与Iterator
类型相对应?
我试图检查是否为某个类型实现了operator fun iterator()
,以查看它是否在后台自动实现了Iterable
,但事实并非如此。我能想到的唯一另一个原因是与Java迭代器的某种互操作性。
class Foo(val n: Int) {
operator fun iterator() = FooIterator(this)
// Shouldn't the language figure out that Foo is iterable?
}
class FooIterator(val foo: Foo): Iterator<Int> {
var seen = false
// Implementation goes here
}
fun <T> printAll(iter: Iterable<T>) {
for (x in iter) {
println("$x")
}
}
fun main() {
printAll(Foo(2)) // Type mismatch: Foo is not Iterable
}
有意义的是,任何实现iterator()
,next()
和hasNext()
,invoke
等的类都将始终实现相应的接口。为什么用这种方式设计语言,而事实并非总是如此?
答案 0 :(得分:4)
这是一条通用规则:在接口中定义具有相同名称/类型的函数不会实现该接口。为什么Iterable
和Iterator
是例外? (技术术语是Kotlin中的子类型是nominal,而不是structural。)
我不知道为什么在任何情况下都将实现操作符fun iterator()而不是Iterable接口。
例如当iterator
是扩展函数时。在the standard library
operator fun <T> Iterator<T>.iterator(): Iterator<T>
operator fun <K, V> Map<out K, V>.iterator(): Iterator<Entry<K, V>>
@JvmName("mutableIterator") operator fun <K, V> MutableMap<K, V>.iterator(): MutableIterator<MutableEntry<K, V>>
如果您很不幸无法使用旧代码,那么next()
/ hasNext()
(还有iterator()
)也可以被定义为java.util.Enumeration
的扩展功能。
答案 1 :(得分:2)
我的理解是operator fun iterator()
,operator fun next()
和operator fun hasNext()
是在语言语法级别定义的,即它们是对语法构造中使用的对象(即{ {1}}循环。
for
另一方面,class Example {
fun someFun() {
for (anInt in NotIterable()) {
...
}
}
}
class NotIterable {
// the 'iterator' returned is not actually an Iterator<> instance
// it just an object which happen to have the right functions
operator fun iterator() : NotIterator {
return NotIterator()
}
}
class NotIterator {
operator fun hasNext(): Boolean {
...
}
operator fun next(): Int {
...
}
}
和Iterable
在语言库中定义。它们建立在运算符功能之上,并添加了丰富而便捷的API,其中包括许多扩展功能。