Kotlin 属性:“属性的类型参数必须在其接收者类型中使用”

Posted

技术标签:

【中文标题】Kotlin 属性:“属性的类型参数必须在其接收者类型中使用”【英文标题】:Kotlin Property: "Type parameter of a property must be used in its receiver type" 【发布时间】:2017-05-25 13:34:26 【问题描述】:

我有以下简单的 Kotlin 扩展函数:

// Get the views of ViewGroup
inline val ViewGroup.views: List<View>
    get() = (0..childCount - 1).map  getChildAt(it) 

// Get the views of ViewGroup of given type
inline fun <reified T : View> ViewGroup.getViewsOfType() : List<T> 
    return this.views.filterIsInstance<T>()

这段代码可以编译并且运行良好。但是,我希望函数getViewsOfType 成为一个属性,就像views 一样。 android Studio 甚至建议这样做。我让 AS 进行重构并生成以下代码:

inline val <reified T : View> ViewGroup.viewsOfType: List<T>
    get() = this.views.filterIsInstance<T>()

但是这段代码无法编译。它会导致错误:“属性的类型参数必须在其接收者类型中使用”

这里有什么问题?搜索有关此错误的帮助似乎无法找到答案。

【问题讨论】:

【参考方案1】:

该错误意味着如果您在接收器类型中使用所述类型 - 您正在扩展的类型,则您只能为扩展属性使用泛型类型参数。

例如,您可以有一个扩展 T 的扩展:

val <T: View> T.propName: Unit
    get() = Unit

或者扩展使用T作为参数的类型:

val <T: View> List<T>.propName: Unit
    get() = Unit

至于为什么会这样,我认为原因是属性不能像函数那样具有泛型类型参数。虽然我们可以调用带有泛型类型参数的函数...

val buttons = viewGroup.getViewsOfType<Button>()

...我认为属性不存在类似的语法:

val buttons = viewGroup.viewsOfType<Button> // ??

【讨论】:

是的,我认为这是正确的。事实上,当这样考虑时,我的 getViewOfType 函数有点没用,因为 Kotlin 已经有一种按类型过滤集合的方法。

以上是关于Kotlin 属性:“属性的类型参数必须在其接收者类型中使用”的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin初识Kotlin之扩展函数与属性

kotlin—lazy及其原理

Kotlin 类属性方法继承多态

Kotlin初识Kotlin之扩展函数与属性

Kotlin属性

Kotlin 什么是幕后字段?