Tia*_*ago 4 generics recursion kotlin
我想生成以下函数:
fun ViewGroup.allRadioButtons(f: (RadioButton) -> Unit){
this.afterMeasured {
for(i in 0 until childCount){
val child = getChildAt(i)
if(child is RadioButton){
f(child)
}
if(child is ViewGroup){
child.allRadioButtons(f)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此RadioButton,我想使用 generic代替 hardcoding T,如下所示:
inline fun <reified T> ViewGroup.allViewsOfTypeT(f: (T) -> Unit){
this.afterMeasured {
for(i in 0 until childCount){
val child = getChildAt(i)
if(child is T){
f(child)
}
if(child is ViewGroup){
child.allRadioButtons(f)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我无法执行上述操作,因为递归函数中不允许具体化类型。
如何在 Kotlin 中泛化该函数?
您可以使递归函数成为非内联函数并采用 aKClass表示所需的类型,并创建一个额外的包装函数:
fun <T : View> ViewGroup.allViewsOfTypeT(type: KClass<T>, f: (T) -> Unit) {
afterMeasured {
for (i in 0 until childCount) {
val child = getChildAt(i)
if (type.isInstance(child)) f(child)
if (child is ViewGroup) child.allViewsOfTypeT(type, f)
}
}
}
inline fun <reified T : View> ViewGroup.allViewsOfTypeT(f: (T) -> Unit)
= allViewsOfTypeT(T::class, f)
Run Code Online (Sandbox Code Playgroud)
你不能内联一个递归函数,除非你可以将它展开到一个循环中,因为内联一个函数意味着在编译之后它不再是一个函数——而是直接复制到调用站点中。没有函数,没有调用栈,没有递归。在这些情况下,您必须传递 aKClass而不是使泛型参数具体化,如果您需要instanceof使用泛型参数进行检查,这基本上就是您在 Java 中所做的。
但是,您可以滚动自己的堆栈(从递归到迭代的方法):
inline fun <reified T : View> ViewGroup.allViewsOfTypeT(action: (T) -> Unit) {
val views = Stack<View>()
afterMeasured {
views.addAll((0 until childCount).map(this::getChildAt))
}
while (!views.isEmpty()) {
views.pop().let {
if (it is T) action(it)
if (it is ViewGroup) {
afterMeasured {
views.addAll((0 until childCount).map(this::getChildAt))
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我还没有测试过这个,但总体思路应该可行。
| 归档时间: |
|
| 查看次数: |
1185 次 |
| 最近记录: |