java - Kotlin 无法获得正确的枚举实例
问题描述
所以我们正在使用 Vaadin。Vaadin 带有一个Key
界面。我复制了它并删除了除CONTROL
键之外的所有条目(出于演示目的,我们不复制实际代码中的类):
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
@FunctionalInterface
public interface VaadinKey extends Serializable {
VaadinKey CONTROL = VaadinKey.of("Control", "ControlLeft", "ControlRight");
//...
static VaadinKey of(String key, String... additionalKeys) {
Objects.requireNonNull(key);
if ("".equals(key)) {
throw new IllegalArgumentException("'key' cannot be empty");
}
List<String> keys = new ArrayList<>();
keys.add(key);
keys.addAll(Arrays.asList(additionalKeys));
return () -> keys;
}
List<String> getKeys();
default boolean matches(String key) {
return getKeys().contains(key);
}
static boolean isModifier(com.vaadin.flow.component.Key key) {
return Stream.of(VaadinKeyModifier.values())
.anyMatch(k -> k.matches(key.getKeys().get(0)));
}
}
该接口由一个KeyModifier
类实现,我也将其复制并剥离:
import java.util.List;
import java.util.stream.Stream;
public enum VaadinKeyModifier implements VaadinKey {
/**
* KeyModifier for "{@code Control}" key.
*/
CONTROL(VaadinKey.CONTROL)
//...
;
private final VaadinKey key;
VaadinKeyModifier(VaadinKey key) {
this.key = key;
}
@Override
public List<String> getKeys() {
return key.getKeys();
}
public static VaadinKeyModifier of(String key) {
return Stream.of(values()).filter(k -> k.matches(key)).findFirst()
.orElseThrow(IllegalArgumentException::new);
}
}
现在让我们尝试从 Kotlin 中使用它:
fun foo() {
val ctrl: VaadinKeyModifier = VaadinKeyModifier.CONTROL
}
这将无法编译,因为
类型不匹配:推断类型是 VaadinKey!但 VaadinKeyModifier 是预期的
(如果我在 IntelliJ 中 ctrl+单击它,它也会带我进入VaadinKey
界面。)
我也试过
import com.[...].VaadinKeyModifier.CONTROL as CONTROL_MODIFIER
fun foo() {
val ctrl: VaadinKeyModifier = CONTROL_MODIFIER
}
结果相同。
现在有趣的是,直接使用 ofVaadinKeyModifier.CONTROL
不会注册 的任何用法VaadinKeyModifier::CONTROL
,而import
变体在导入中注册了一种用法(但这并不能防止编译错误)。
是什么赋予了?
为什么会这样?
我如何让它发挥作用?
解决方案
枚举实例的名称 ( CONTROL
) 与其从接口继承的同名字段冲突。
在 Java 中,这种歧义解决了有利于枚举实例,在 Kotlin(在 Java 互操作期间)由于某种原因它解决了有利于字段。然而,如果VaadinKeyModifier
类是在 Kotlin 中定义的,它会被解决为有利于枚举:
enum class VaadinKeyModifierKT(private val key: VaadinKey) : VaadinKey {
CONTROL(VaadinKey.CONTROL);
}
val ctrl: VaadinKeyModifierKT = VaadinKeyModifierKT.CONTROL //Would be compiled
如果更改给定代码以避免这种歧义(例如,通过重命名字段/枚举或分离接口和这些字段)不是一种选择,那么您可以VaadinKeyModifier
通过其名称访问实例:
val ctrl = enumValueOf<VaadinKeyModifier>("CONTROL")
作为一个不易出错的选项,我建议创建辅助枚举,复制 的值VaadinKeyModifier
,使用转换器VaadinKeyModifier
输入:
enum class Modifier {
SHIFT,
CONTROL,
ALT,
ALT_GRAPH,
META;
fun toVaadinKeyModifier() : VaadinKeyModifier = enumValueOf(name)
}
//Usage:
val ctrl: VaadinKeyModifier = Modifier.CONTROL.toVaadinKeyModifier()
推荐阅读
- elixir - “找不到#PID<0.94.0> 的迁移运行程序进程”是什么意思以响应混合ecto.migrate?
- python - 在 Python 中为 Terraform 应用程序初始化一个新的 CDKTF
- tensorflow - 如何在使用 Residual Skip Connections(基于 ResNet 的自动编码器)的 Keras(tensorflow.keras)中构建自动编码器/U-Net?
- javascript - 如何在 javascript 或 jquery 中提交一组值?
- javascript - 将带有图像的 html 表导出到 xlsx - Javascript
- node.js - 如何在 Google Cloud Function 中通过 HTTP 响应发送大文件
- swift - Swift - 如何使用枚举字典初始化变量?
- r - 如何更改颜色索引中的中间值?
- selenium - 如何使用 java 处理 Selenium 中的自动建议?
- udp - 有没有办法通过 udp 检查来自源的 rtp 流?