首页 > 解决方案 > 在构造函数中使用模板类

问题描述

这是我的情况的最小示例:

class Foo<T>(val list: List<Any>) {
    init {
        list.filterIsInstance<T>().forEach { ... } // error
    }
}

自然,这不会编译:

Cannot use 'T' as reified type parameter. Use a class instead.

这种情况的惯用解决方案是什么?听起来编译器建议将 aKClass<T>作为构造函数参数,但这种用法是什么样的?

标签: genericskotlin

解决方案


这里有多个问题。首先,你有一个你指定的错误,因为T你的类Foo的 type 参数没有reified。因此,您需要reified声明类型参数的关键字。但是,您需要一个inline函数才能做到这一点(因为 JVM 的限制,Kotlin 应该支持)。问题是,你不能让构造函数inline在 Kotlin 中。

最接近您需要的是以下内容:

class Foo<T>(val list: List<T>) {

    init {
        list.forEach { println(it) }
    }

    companion object {

        inline fun <reified T> create(list: List<Any>): Foo<T> {
            return Foo(list.filterIsInstance<T>())
        }
    }
}

以上假设您只需要从列表中获取作为某个类的实例的所有元素,并且只使用Foo类中的这些元素。

更新:即使您希望Foo自己实例上的类型参数被具体化,这在 Kotlin 中根本不可能(如上所述,由于 JVM 限制)。

那么你需要确保创建时传递的类型是相同的吗?美好的。那么除了指定一个额外的参数之外别无他法:

class Foo<T>(val list: List<Any>, `class`: Class<T>) {
    init {
        list.filter { `class`.isInstance(it) }.forEach { println(it) }
    }
}

您没有指定要对获得的列表做什么,以及为什么需要严格相同的类型,但我个人不会为此烦恼并使用第一个变体。


推荐阅读