Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果映射中不存在,则映射抛出NoTouchElementException的Kotlin委托属性_Kotlin - Fatal编程技术网

如果映射中不存在,则映射抛出NoTouchElementException的Kotlin委托属性

如果映射中不存在,则映射抛出NoTouchElementException的Kotlin委托属性,kotlin,Kotlin,我将kotlin对象定义为: data class UserUpdateRequest(val map: Map<String, Any?>) { @get:Email val email: String? by map val firstName: String? by map val lastName: String? by map } 数据类UserUpdateRequest(val-map:map){ @获取:电子邮件 val电子邮件:字符串

我将kotlin对象定义为:

data class UserUpdateRequest(val map: Map<String, Any?>) {
    @get:Email
    val email: String? by map
    val firstName: String? by map
    val lastName: String? by map
}
数据类UserUpdateRequest(val-map:map){
@获取:电子邮件
val电子邮件:字符串?按地图
val firstName:字符串?按映射
val lastName:字符串?按映射
}
这很好,所以我遇到的问题是属性是可以为空的,当我访问一个属性时,比如通过执行
instance.email
它会抛出一个
NoTouchElementException
,如果映射中没有设置该属性

相反,如果它返回
null
,则会更方便,因为它是可选的/可空的。在不编写我自己的委托的情况下,有什么方法可以实现这一点吗?

您基本上可以使用为委托包装
映射的扩展,以便它执行lambda来计算缺席键上的值:

data class UserUpdateRequest(val map: Map<String, Any?>) {
    private val defaultMap = map.withDefault { null }

    @get:Email
    val email: String? by defaultMap
    val firstName: String? by defaultMap
    val lastName: String? by defaultMap
}
数据类UserUpdateRequest(val-map:map){
private val defaultMap=map.withDefault{null}
@获取:电子邮件
val电子邮件:字符串?按默认映射
val firstName:字符串?按默认映射
val lastName:String?按默认映射
}

请注意,简单的
defaultMap.get(key)
defaultMap[key]
查询不由此包装器处理,它只影响
defaulMap.getValue(key)
调用(委托实现也会使用这些调用)。

下面是一个委托实现,如果您想更多地控制代理的工作并了解其工作方式

演示如何在您的场景中使用它的第一步: 在上面的例子中,实际上我们调用

initialMap["lastName"] = "Genericname"
如果变量名和对应的键不同,甚至可以将键作为参数传递。
通过这种方法,您可以在getValue和setValue函数中自行处理值访问

希望这对任何人都有帮助

fun <R>valueFromMap(key: (KProperty<*>) -> String = KProperty<*>::name,
                map: Map<String, Any?>): ReadWriteProperty<Any, R?>{

    val myMap = map.toMutableMap()

    return object : ReadWriteProperty<Any, R?> {

    override fun getValue(thisRef: Any, property: KProperty<*>): R? {
        return (myMap.getOrDefault(key(property), null) as? R)?: return null
    }

    override fun setValue(thisRef: Any, property: KProperty<*>, value: R?) {
        if(value == null){
            myMap.remove(key(property))
        } else {
            myMap[key(property)] = value
        }
    }
}
request.lastName = "Genericname"
initialMap["lastName"] = "Genericname"