如何在 Kotlin 中创建具体化类型的对象
How to create object of a reified type in Kotlin
我试图创建一个扩展函数来为回收器视图适配器创建视图持有者的对象
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 的对象,以便我可以 return 从函数。
这个解决方案非常丑陋,但我假设 "theoretically" 可以工作:
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(view: View)
的T
的构造函数
2. 在该构造函数上调用 newInstance
,将其传递给您膨胀的视图
改编自https://discuss.kotlinlang.org/t/generic-object-creation/1663/5
的解决方案
只需通过以下方式调用它:
val viewHolder = my_view_group.create<MyViewHolder>(R.layout.my_layout)
一个干净的替代解决方案是显式传递构造函数。它甚至不会更冗长,因为类型参数可以推断出来,不需要再指定了。像这样使用:
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)
}
不是上述问题的答案,但应该对那些来到这里想要摆脱 Thing(Foo::class.java, ...)
并使用 Thing<Foo>(...)
.
的人有所帮助
您需要做的就是在 companion object
中添加一个具体化的 invoke
。
之前
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>(...)
我试图创建一个扩展函数来为回收器视图适配器创建视图持有者的对象
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 的对象,以便我可以 return 从函数。
这个解决方案非常丑陋,但我假设 "theoretically" 可以工作:
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(view: View)
的T
的构造函数
2. 在该构造函数上调用 newInstance
,将其传递给您膨胀的视图
改编自https://discuss.kotlinlang.org/t/generic-object-creation/1663/5
的解决方案只需通过以下方式调用它:
val viewHolder = my_view_group.create<MyViewHolder>(R.layout.my_layout)
一个干净的替代解决方案是显式传递构造函数。它甚至不会更冗长,因为类型参数可以推断出来,不需要再指定了。像这样使用:
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)
}
不是上述问题的答案,但应该对那些来到这里想要摆脱 Thing(Foo::class.java, ...)
并使用 Thing<Foo>(...)
.
您需要做的就是在 companion object
中添加一个具体化的 invoke
。
之前
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>(...)