带有通用参数的Kotlin抽象类和使用类型参数的方法

Nik*_*laB 8 generics abstract-class type-inference kotlin

我正在尝试使用泛型参数创建一个抽象类,它将具有应该调用方法而不必指定类型参数的子类.到目前为止我有这个:

abstract class AbstractClass<T : Any> @Autowired constructor(protected val delegate: MyService) {
    inline fun <T: Any> myMethod(param: Any): T? {
        return delegate.myMethod(param).`as`(T::class.java)
    }
}
Run Code Online (Sandbox Code Playgroud)

并实施:

class TesterWork @Autowired constructor(delegate: MyService) : AbstractClass<Tester>(delegate) {
}
Run Code Online (Sandbox Code Playgroud)

现在在调用时myMethod我必须指定类型参数:

testerWork.myMethod<Tester>("test")
Run Code Online (Sandbox Code Playgroud)

我想知道是否可以自动推断出类型参数?我可以以某种方式重写myMethod吗?请注意,我需要T::class.java在方法内部.

hot*_*key 8

您不能将类的泛型参数用作具体化的泛型(获取其T::class令牌),因为在运行时,泛型参数被删除:Kotlin遵循Java的类型擦除实践,并且没有针对类的具体化泛型.
(Kotlin 仅为内联函数修改了泛型)

鉴于此,您可以通过并存储Class<T>令牌以便您可以使用它.

此外,myFunction在您的示例中引入了一个泛型参数,它将是一个新的泛型,不以任何方式连接到类泛型参数(命名两者T只会增加混淆,考虑它们T1T2).如果我做对了,你的意思就是"通用".

您可以做的是声明一个抽象val,它将存储一个类令牌并重写该函数,以便它使用存储的类令牌:

abstract class AbstractClass<T : Any> constructor(protected val delegate: MyService) {
    protected abstract val classToken: Class<T>

    fun myMethod(param: Any): T? {
        return delegate.myMethod(param).`as`(classToken)
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,派生AbstractClass将需要覆盖classToken:

class TesterWork constructor(delegate: MyService) : AbstractClass<Tester>(delegate) {
    override val classToken = Tester::class.java
}
Run Code Online (Sandbox Code Playgroud)

之后,您将能够在TesterWork实例上调用该函数,而无需指定泛型参数:

val service: MyService = ...
val t: Tester? = TesterWork(service).myMethod("test")
Run Code Online (Sandbox Code Playgroud)