gpt4 book ai didi

使用 DefaultValue 委托(delegate)映射的 Kotlin 问题 - 语言错误?

转载 作者:行者123 更新时间:2023-12-05 02:33:31 25 4
gpt4 key购买 nike

在下面的代码中,MyMap 简单地实现了 Map by 委托(delegate)给 impl:

foo@host:/tmp$ cat Foo.kt
class MyMap <K, V> (val impl : Map <K, V>) : Map<K, V> by impl {
fun myGetValue (k: K) = impl.getValue(k)
}

fun main() {
val my_map = MyMap(mapOf('a' to 1, 'b' to 2).withDefault { 42 })
println(my_map.myGetValue('c')) // OK
println(my_map.getValue('c')) // ERROR
}

为什么我在第二个 println 上出现以下错误?

foo@host:/tmp$ /path/to/kotlinc Foo.kt
foo@host:/tmp$ /path/to/kotlin FooKt
42
Exception in thread "main" java.util.NoSuchElementException: Key c is missing in the map.
at kotlin.collections.MapsKt__MapWithDefaultKt.getOrImplicitDefaultNullable(MapWithDefault.kt:24)
at kotlin.collections.MapsKt__MapsKt.getValue(Maps.kt:344)
at FooKt.main(Foo.kt:8)
at FooKt.main(Foo.kt)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.jetbrains.kotlin.runner.AbstractRunner.run(runners.kt:64)
at org.jetbrains.kotlin.runner.Main.run(Main.kt:176)
at org.jetbrains.kotlin.runner.Main.main(Main.kt:186)
foo@bigdev:/tmp$

更新:编译器和运行时版本输出为:

foo@host:/tmp$ kotlinc -version
info: kotlinc-jvm 1.6.10 (JRE 17.0.1+12-LTS)
foo@host:/tmp$ kotlin -version
Kotlin version 1.6.10-release-923 (JRE 17.0.1+12-LTS)
foo@host:/tmp$ javac -version
javac 17.0.1
foo@host:/tmp$ java -version
openjdk version "17.0.1" 2021-10-19 LTS
OpenJDK Runtime Environment Corretto-17.0.1.12.1 (build 17.0.1+12-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.1.12.1 (build 17.0.1+12-LTS, mixed mode, sharing)

最佳答案

这是因为 withDefault 的实现方式有点出乎意料。 withDefault 生成的包装器不会覆盖 getValue() 因为这是不可能的,因为 getValue() 是一个扩展函数。所以不幸的是,我们拥有的是一个经典的 OOP 反模式:getValue() 执行一个 is 检查以查看它是否在内部 MapWithDefault< 上被调用 接口(interface),只有在这种情况下才使用默认值。我看不出他们有什么办法可以在不违反 Map 契约(Contract)的情况下避免这种情况。

myGetValue 在底层委托(delegate)上调用 getValue,这是一个 MapWithDefault,因此它工作正常。

MyMap 实例上调用的

getValue 将无法通过内部 is MapWithDefault 检查,因为 MyMap 不是 MapWithDefault,即使它的委托(delegate)是。委托(delegate)其他类型不会传播到委托(delegate)给它的类,这是有道理的。就像我们委托(delegate)给 MutableMap 一样,我们可能希望该类仅被视为只读 Map。

关于使用 DefaultValue 委托(delegate)映射的 Kotlin 问题 - 语言错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70968150/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com