0

I'm trying this:

class Foo<T> {
    var member: T = T()
}

...but the Kotlin compiler gives me an error: Type parameter T cannot be called as function.

How do I default-construct a generic member variable?

Roger Lipscombe
  • 89,048
  • 55
  • 235
  • 380
  • 1
    Does this answer your question? [Is there any equivalent of C#'s "default" keyword for Kotlin?](https://stackoverflow.com/questions/61159046/is-there-any-equivalent-of-cs-default-keyword-for-kotlin) – Kacper Apr 02 '21 at 21:07
  • Well, yeah, apart from the fact that my question is significantly more concise... – Roger Lipscombe Apr 02 '21 at 21:10
  • 1
    But still it is about the same topic. You both want to have default instance of some type T. And answer is given that it is not possible in kotlin. You have to either use nullable type or provide instance of the class. – Kacper Apr 02 '21 at 21:15
  • It’s not possible because Kotlin doesn’t support default types. – Tenfour04 Apr 02 '21 at 22:49
  • It's implied that `T` has a public no-arg constructor, but in general case it may not be true. – Михаил Нафталь Apr 02 '21 at 23:07

2 Answers2

1

Well, to access the type information, we need to use the reified keyword on the type, but this is only applicable in inlined functions. So instead of relying on direct construction, a workaround can be to use a generator function wrapped in the companion object that immediately sets the member right after construction

// Test class to verify the implementation
class Yolo {
    override fun toString() = "Yolo swag"
}

class Foo<T : Any> {
    lateinit var member: T
    
    companion object {
        inline fun <reified T : Any> newInstance() = 
            T::class.java.newInstance().let { memberInstance ->
                Foo<T>().apply { member = memberInstance} 
            }
    }
}

fun main() {
    // generate a Foo<Yolo>
    val foo = Foo.newInstance<Yolo>()
    
    println(foo.member) // displays "Yolo swag"
}
Wang
  • 1,028
  • 7
  • 12
0

It's implied that T has a public no-arg constructor, but in general case it may not be true. This code uses reflection to bypass compiler complains about it (which may end up with runtime error if you dissapoint the JVM expectations and indeed pass T without public no-arg constructor).

//Reified generics at class level are not yet supported in Kotlin (KT-33213), 
// so you have to pass instance of `KClass` manually as a consructor parameter
class Foo<T : Any>(clazz: KClass<T>) { 
    var member: T = clazz.createInstance() 
}