Kotlin合同具有高阶函数



我对Kotlin的可空性有问题,我想知道我能用合同解决它吗。对于这样的Java接口:interface Action<T>{ void execute(T param); },有两个扩展:

fun <T, R> Action<T>.map(mapper:(R)->T): Action<R> {
return Action{ execute(mapper(it)) }
}

fun <T> Action<T>.ifNotNull(): Action<T> {
return Action { if(it != null) execute(it) }
} 

还有一个具有可为空数据的通用模型:

class Model<T>(val data: T?)

现在我已经创建了以Action接口为参数的函数。情况是只有在param != null时才执行动作参数,所以它看起来如下:

fun <T> callback(model: Model<T>, action: Action<T>){
action
.map{ it.getData() } //compilation error: getData return T? when action require T
.ifNotNull() //execute only when data!=null
.execute(model)
}

那么,现在有没有任何选项可以使用Kotlin合约来确保编译器action不会使用null参数执行?

ModelAction在您自己的答案中只是为ifNotNull():提供了正确的签名

fun <T> Action<T>.ifNotNull(): Action<T?> {
return Action { if(it != null) execute(it) }
} 

那么你的操作顺序就错了:

fun <T> callback(model: Model<T>, action: Action<T>){
action
.ifNotNull() // Action<T?>
.map { model: Model<T> -> model.data } // Action<Model<T>>
.execute(model)
}

请注意,编译器将无法为这种map用法推断R。你也可以把它写成

fun <T> modelAction(action: Action<T>): Action<Model<T>> {
return action
.ifNotNull()
.map { it.data }
}

顺便说一句,这个论点是map的"错误方法";这样的函数通常被称为CCD_ 11。

如果是无界的,则默认情况下,所有类型参数都以可为null的形式提供(换句话说,它们是从Any?派生的(。解决这个问题的简单方法就是在类型参数上指定非null绑定:<T : Any>

我创建了专门用于此用途的Action接口实现,如下所示:

class ModelAction<T>(val action: Action<T>) : Action<T?> {
override fun execute(param: T?) {
param?.let {
action.execute(it)
}
}
}
fun callback<T>(model: Model<T>, action: Action<T>){
ModelAction(action)
.map{ it.getData() } 
.execute(model)
}

这个想法可能会帮助有类似问题的人,但它不符合我的期望,我仍然指望基于高阶函数的解决方案。

相关内容

  • 没有找到相关文章

最新更新