这是一个简单的泛型方法,并且在for循环中传递args的值会导致错误说明:
for-loop范围必须具有和iterator()方法
fun main(args: Array<String>) {
val arr: IntArray = intArrayOf(1,2,3,4)
val charA: CharArray = charArrayOf('a','b','c','d')
printMe(arr)
printMe(charA)
}
fun <T>printMe(args: T){
for (items in args){
println(items)
}
}
如何让它迭代char[]
和array
答案 0 :(得分:5)
for循环按惯例工作,为名为iterator
的运算符成员静态查找 ,该成员必须返回可以迭代的内容,即依次为运算符成员{{ 1}}和next
。
hasNext
修饰符需要指定该成员是否满足某些约定,即迭代约定。
由于operator
的类型为args
且每种可能的类型T
都没有iterator
成员,因此无法轻松迭代。
但是你可以为T
提供一个额外的参数,它知道如何从printMe
的实例中获取迭代器,然后用它来获取迭代器并迭代它:
T
此处fun main(args: Array<String>) {
val arr: IntArray = intArrayOf(1,2,3,4)
val charA: CharArray = charArrayOf('a','b','c','d')
printMe(arr, IntArray::iterator)
printMe(charA, CharArray::iterator)
}
fun <T> printMe(args: T, iterator: T.() -> Iterator<*>) {
for (item in args.iterator()) {
println(item)
}
}
是表示function with receiver的类型。可以在T.() -> Iterator<*>
上调用该类型的实例,就好像它们是它的扩展名一样。
这个片段有效,因为返回的迭代器本身就有一个操作符扩展函数T
,它只返回迭代器,因此允许用for循环遍历迭代器。
答案 1 :(得分:2)
这实际上有点微妙。
关键问题是变量arr
的类型为IntArray
而IntArray
不是来自Array
。同样,虽然IntArray
具有iterator()
功能,但它并未实现Iterable<>
。
CharArray
变量也是如此。
事实上,IntArray
和CharArray
以及Array<T>
似乎没有Any
以外的任何公共基类或接口。所以你要么在printMe
中传递一个对象并进行类型检查,要么使用重载。
类型检查版本看起来像
printMe(args:Any) {
if(args is IntArray) {
for(item in args) {
println(item)
}
} else if (args is CharArray) {
for(item in args) {
println(item)
}
} else {
println("Not an IntArray or a CharArray")
}
}
重载看起来像这样
printMe(args:IntArray) {
for(item in args) {
println(item)
}
}
printMe(args:CharArray) {
for(item in args) {
println(item)
}
}
IMO重载是更好的选择,因为你不能最终传递一个你不能错误处理的对象。
答案 2 :(得分:0)
问题是编译器不知道你传递Array
而T
可以是任何类型。
解决此问题的一种方法是使用is
运算符:
fun <T>printMe(args: T){
if(args is Array<*>) {
for (items in args) {
println(items)
}
}
}