【问题标题】:Default value for generic member通用成员的默认值
【发布时间】:2021-04-03 07:28:24
【问题描述】:

我正在尝试这个:

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

...但是 Kotlin 编译器给了我一个错误:Type parameter T cannot be called as function

如何默认构造一个泛型成员变量?

【问题讨论】:

  • 嗯,是的,除了我的问题要简洁得多...
  • 但它仍然是关于同一个主题。你们都想拥有某种类型 T 的默认实例。并且给出的答案是在 kotlin 中这是不可能的。您必须使用可空类型或提供类的实例。
  • 不可能,因为 Kotlin 不支持默认类型。
  • 暗示T 有一个公共的无参数构造函数,但一般情况下它可能不是真的。

标签: kotlin


【解决方案1】:

好吧,要访问类型信息,我们需要在类型上使用reified 关键字,但这仅适用于内联函数。因此,不依赖于直接构造,一种解决方法是使用包装在伴随对象中的生成器函数,该生成器函数在构造后立即设置成员

// 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"
}

【讨论】:

    【解决方案2】:

    暗示T 有一个公共的无参数构造函数,但一般情况下它可能不是真的。此代码使用反射绕过编译器抱怨它(如果您对 JVM 期望不满意并且确实在没有公共无参数构造函数的情况下通过 T ,最终可能会出现运行时错误)。

    //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() 
    }
    

    【讨论】:

      猜你喜欢
      • 2016-09-19
      • 2012-11-22
      • 1970-01-01
      • 1970-01-01
      • 2012-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-06
      相关资源
      最近更新 更多