generics - 在构造函数中使用模板类

标签 generics kotlin

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

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

自然,这不会编译:
Cannot use 'T' as reified type parameter. Use a class instead.
这种情况的惯用解决方案是什么?听起来好像编译器建议使用KClass<T>作为构造函数参数,但是这种用法是什么样的?

最佳答案

这里有多个问题。首先,您指定了一个错误,因为您的类T的类型参数Foo没有被验证。因此,您需要在声明type参数的位置使用关键字 reified 。但是然后,您将需要一个 inline 函数才能做到这一点(由于Kotlin应该支持的JVM限制)。问题是,您不能使构造函数在Kotlin中成为 inline

您可以根据需要找到的最接近的是:

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

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

关于generics - 在构造函数中使用模板类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60554185/

相关文章:

java - 这些通用声明之间有什么区别?

具有泛型、比较器和排序错误的 Java 类层次结构

sql - 使用 Ktor + Exposed (Kotlin) 进行数据库迁移的推荐方法是什么?

Gradle多项目buildSrc在子项目中不起作用

ios - 返回调用对象类型的方法

c# - Unity - 解析继承自 T 的泛型实现

java - 我可以在 HashMap 中通过 Key 实现类型安全吗?

java - @PropertyKey 注解不适用于 Kotlin,但适用于 Java

java - 如何更改BottomSheetDialogFragment的BottomSheetBehavior?

android - RecyclerView 添加新项目时滚动返回到列表顶部