如何在Kotlin中创建具体类型的对象

时间:2018-05-24 13:42:04

标签: android kotlin recycler-adapter kotlin-extension kotlin-reified-type-parameters

我正在尝试创建一个扩展函数来为Recycler视图适配器创建视图持有者对象

inline fun <reified T: RecyclerView.ViewHolder> ViewGroup.createViewHolder(@LayoutRes res: Int): T {
    val inflater = LayoutInflater.from(context)
    val itemView = inflater.inflate(res, this, false)
    // return ViewHolder Object
}

如何创建扩展RecyclerView.ViewHolder的T类型的对象,以便我可以从函数返回。

3 个答案:

答案 0 :(得分:6)

一个干净的替代解决方案是显式传递构造函数。它甚至不会更冗长,因为可以推断出类型参数,不需要再指定。使用方式如下:

val viewHolder = my_view_group.create(::MyViewHolder, R.layout.my_layout)

像这样实施:

inline fun <reified T: RecyclerView.ViewHolder> ViewGroup.create(createHolder: (View) -> T, @LayoutRes res: Int): T {
    val inflater = LayoutInflater.from(context)
    val itemView = inflater.inflate(res, this, false)
    return createHolder(itemView)
}

答案 1 :(得分:2)

这个解决方案非常难看,但我认为“理论上”可以起作用:

inline fun <reified T: RecyclerView.ViewHolder> ViewGroup.create(@LayoutRes res: Int): T {
        val inflater = LayoutInflater.from(context)
        val itemView = inflater.inflate(res, this, false)
        return T::class.java.getConstructor(View::class.java).newInstance(itemView)
    }

最后一行的作用是: 1.获取匹配T的{​​{1}}构造函数 2.在该构造函数上调用T(view: View),向其传递您膨胀的视图

改编自https://discuss.kotlinlang.org/t/generic-object-creation/1663/5

的解决方案

只需通过以下方式致电:

newInstance

答案 2 :(得分:0)

不是所述问题的答案,但应该对到达这里想要摆脱 Thing(Foo::class.java, ...) 并使用 Thing<Foo>(...) 的人有所帮助。

您需要做的就是在 invoke 中添加具体化的 companion object

之前

class Thing<E : Enum<E>>(cls: Class<E>, value: String? = null) : Iterable<E> {
    ...
}

val thing = Thing(Foo::class.java, ...)

之后

class Thing<E : Enum<E>>(cls: Class<E>, value: String? = null) : Iterable<E> {
    ...
    companion object {
        // Lets us construct using Thing<Foo>(...) instead of Thing(Foo::class.java, ...)
        inline operator fun <reified T : Enum<T>> invoke(value: String? = null) = Thing(T::class.java, value)
    }
}

val thing = Thing<Foo>(...)