Generics 如何在Kotlin中将vararg与不同的泛型一起使用?
我想将vararg与具有不同类型的每个参数的泛型一起使用 我已经尝试过的:Generics 如何在Kotlin中将vararg与不同的泛型一起使用?,generics,kotlin,Generics,Kotlin,我想将vararg与具有不同类型的每个参数的泛型一起使用 我已经尝试过的: class GeneralSpecification<T> { fun <P> ifNotNullCreateSpec(vararg propToCreateFun: Pair<P?, (P) -> Specification<T>>): List<Specification<T>> = propToCreateFun.
class GeneralSpecification<T> {
fun <P> ifNotNullCreateSpec(vararg propToCreateFun: Pair<P?, (P) -> Specification<T>>): List<Specification<T>> =
propToCreateFun.mapNotNull { (prop, funCreateSpec) ->
prop?.let(funCreateSpec)
}
...
}
(vararg对中的不同类型)
当我需要限制vararg中的类型时,如何将vararg与不同的泛型一起使用?(pair.first类型取决于pair.second类型)如果要将不同的函数存储在一起,则需要将参数类型
T
与out
变量一起处理。这意味着T
仅用于类的输出。实际上,这意味着如果派生的扩展/实现了基本的,则允许规范的转换
如果没有这样的约束,函数类型是不相关的,因此不能将它们存储在公共数组中(varargs只是数组参数的语法糖)
例如:
class Spec<out T>
fun createStringSpec() = Spec<String>()
fun createIntSpec() = Spec<Int>()
fun <T> ifNotNullCreateSpec(vararg pairs: Pair<T, () -> Spec<T>>) = Unit
fun main() {
ifNotNullCreateSpec("asdf" to ::createStringSpec, 5 to ::createIntSpec)
}
类规范
fun createStringSpec()=Spec()
fun createIntSpec()=Spec()
有趣的ifNotNullCreateSpec(vararg对:对规范>)=单位
主要内容(){
ifNotNullCreateSpec(“asdf”到::createStringSpec,5到::createIntSpec)
}
使用参数T
,如(T)->Spec
,函数类型的输入中也会出现T
类型。这意味着您不能再将函数类型存储在一起,因为它们采用不同类型的参数——您将使用哪种类型调用这样的函数
你需要做的是找到最常见的分母。一个示例是接受任何参数,并对实际类型执行运行时检查/分派
参见我最近的答案:
而不是使用<代码>配对>代码>,考虑定义自己的类型:
class WithSpec<P, T>(val prop: P?, val funCreateSpec: (P) -> Specification<T>) {
fun spec() = prop?.let(funCreateSpec)
}
class-with-spec(val-prop:P?,val-funCreateSpec:(P)->规范){
fun spec()=prop?.let(funCreateSpec)
}
为什么??因为它允许你做
class GeneralSpecification<T> {
fun ifNotNullCreateSpec(vararg propToCreateFun: WithSpec<*, T>): List<Specification<T>> =
propToCreateFun.mapNotNull { it.spec() }
...
}
ifNotNullCreateSpec(WithSpec("asdf", ::createStringSpec), WithSpec(5, ::createIntSpec))
类通用规范{
fun ifNotNullCreateSpec(vararg propToCreateFun:WithSpec):列表=
propToCreateFun.mapNotNull{it.spec()}
...
}
ifNotNullCreateSpec(带spec(“asdf”),带spec(5,::createIntSpec))
如果您想更接近原始代码,可以轻松地将添加到使用spec返回的类似于的扩展函数中
看看你是否不知道*
是什么意思。很好的解决方案,谢谢!我必须更深入一点:使用这个infix-funP?.ifNonNull(createSpecFun:(P)->规范)=这个?.let(createSpecFun)
我通过以下方式获得一个规范列表:combinepc(specifications:list)
和combinepc(listOf(“asdf”ifNonNull::createForName))
是的,这也是完全合理的。当然,您可以使用vararg
来创建combineSpec
。
class GeneralSpecification<T> {
fun ifNotNullCreateSpec(vararg propToCreateFun: WithSpec<*, T>): List<Specification<T>> =
propToCreateFun.mapNotNull { it.spec() }
...
}
ifNotNullCreateSpec(WithSpec("asdf", ::createStringSpec), WithSpec(5, ::createIntSpec))