What is the proper way to create new instance of generic class in kotlin?

前端 未结 2 1161
萌比男神i
萌比男神i 2020-12-09 08:37

I use following initialization:

val entityClass = javaClass>()
var entity = entityClass.newInstance().newInstance()

bu

相关标签:
2条回答
  • 2020-12-09 09:21

    Thanks to Kirill Rakhman I wrote a similar answer (for Android adapter). A difference here is in a parameter of the class.

    private fun <T> createItem(
        viewGroup: ViewGroup,
        layoutRes: Int,
        method: (View) -> T
    ): T {
        val view = LayoutInflater.from(viewGroup.context).inflate(layoutRes, viewGroup, false)
        return method(view) // Creates T(view).
    }
    

    Then use it this way:

    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): AbstractViewHolder {
        return when (viewType) {
            LOADER -> createItem(viewGroup, R.layout.row_loader, ::LoaderViewHolder)
            DATE -> createItem(viewGroup, R.layout.row_date, ::DateViewHolder)
            else -> throw IllegalStateException("Wrong class")
        }
    }
    

    Here LoaderViewHolder and DateViewHolder are descendants of AbstractViewHolder.

    0 讨论(0)
  • 2020-12-09 09:23

    If you let IntelliJ add explicit type information, you see that entityClass is actually of type Class<Class<String>>. I'm not sure if that's what you want. In line 2 you are first creating an instance of Class<T> and then one of T but that's not possible anyway, because the generic information about T is lost at runtime. Apart from that you can't instantiate class objects directly.

    Solution

    One possible solution would be to add a parameter of type Class<T> to your function or class and use it to instantiate objects like this.

    fun <T> foo(entityClass: Class<T>) {
        var entity: T = entityClass.newInstance()
    }
    
    fun test() {
        foo(Object::class.java)
    }
    

    But there's actually a more elegant solution without the use of reflection. Define a parameter of method type () -> T and use constructor references. Here's my related question about constructor references and here's the code:

    fun <T> foo2(factory: () -> T) {
        var entity: T = factory()
    }
    
    fun test() {
        foo2(::Object)
    }
    
    0 讨论(0)
提交回复
热议问题