How to instantiate a new instance of generic type

后端 未结 2 813
温柔的废话
温柔的废话 2021-01-01 16:38

In C# you can place a new constraint on a generic to create a new instance of the generic parameter type, is there an equivalent in Kotlin?

Right now my work aroun

相关标签:
2条回答
  • 2021-01-01 16:56

    A solution:

    1/ use an inline function with preserved param type (reified type)

    2/ in this inline function, invoque the needed constructor using class introspection (reflexion *) /!\ an inline function can't be nested/embedded in a class or function

    Let see how it works on a simple example:

    // Here's 2 classes that take one init with one parameter named "param" of type String
    //!\ to not put in a class or function
    
    class A(val param: String) {}
    class B(val param: String) {}
    
    // Here's the inline function.
    // It returns an optional because it could be passed some types that do not own
    // a constructor with a param named param of type String
    
    inline fun <reified T> createAnInstance(value: String) : T? {
    
        val paramType = String::class.createType() //<< get createAnInstance param 'value' type
    
        val constructor = T::class.constructors.filter {
            it.parameters.size == 1 && it.parameters.filter { //< filter constructors with 1 param
                it.name == "param" && it.type == paramType //< filter constructors whose name is "param" && type is 'value' type
            }.size != 0
        }.firstOrNull() //< get first item or returned list or null
    
        return constructor?.call(value) // instantiate the class with value
    
    }
    
    // Execute. Note that to path the type to the function val/var must be type specified. 
    
    val a: A? = createAnInstance("Wow! A new instance of A")
    
    val b: B? = createAnInstance("Wow! A new instance of B")
    

    *) kotlin-reflect.jar must be included in the project

    In Android Studio: add to build.gradle(Module: app): implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

    0 讨论(0)
  • 2021-01-01 17:16

    Currently, that's not possible. You can give a thumbs-up for the issue https://youtrack.jetbrains.com/issue/KT-6728 to vote for the addition of this feature.

    At least, you can leave out the generic type because Kotlin can infer it:

    someMethod(::MyClass)
    
    0 讨论(0)
提交回复
热议问题