从kotlin调用的第三方java库中的重载解析歧义

m4pnthwp  于 2021-07-05  发布在  Java
关注(0)|答案(2)|浏览(311)

我在kotlin写了一个小程序,它使用库https://github.com/kaptainwutax/seedutils,特别是维度枚举https://github.com/kaptainwutax/seedutils/blob/master/src/main/java/kaptainwutax/seedutils/mc/dimension.java
当我打电话时。 Dimension.OVERWORLD.name ,我明白了 Overload resolution ambiguity . 我知道问题是什么,问题是 enum Dimensionname 字段,并且枚举类本身 name 字段https://kotlinlang.org/docs/reference/enum-classes.html
问题是,我能做些什么。我目前的方法是分叉这个库和我使用并依赖它的所有其他4个库,重命名 name 在那个枚举中,我不喜欢用5个repos来重命名一个字段。
有没有别的办法来解决这个问题?我可以指定应该使用哪个名称吗?有没有办法通过告诉jvm做什么来消除这种模糊性?
或者是没有什么要做的并且命名枚举字段 name kotlin是否有有效的方法使其无法使用?

ztmd8pv5

ztmd8pv51#

除了@jonskeet提供的解决方法之外,可能还有其他一些方法。我能想到的就是简单地使用普通的java反射api和kotlin扩展方法:

private val nameField = Dimension::class.java.getDeclaredField("name")
fun Dimension.getName() = nameField.get(this) as String

你可以这样称呼它:

val name = Dimension.OVERWORLD.getName()

可悲的是,这对kotlin反射不起作用,因为这样我们就会遇到同样的错误:

Dimension::name // Overload resolution ambiguity

这种使用反射的方法也可以改进,只需查找一次名称。为此,创建一个包含 Map<Dimension, String> :

private object NameHolder {
    val dimensionToName = EnumMap<Dimension, String>(Dimension::class.java)
    init {
        val nameField = Dimension::class.java.getDeclaredField("name")
        for (dimension in Dimension.values()) {
            dimensionToName[dimension] = nameField.get(dimension) as String
        }
    }
}

然后将扩展方法更改为:

fun Dimension.getName() = NameHolder.dimensionToName[this]!!
i86rm4rw

i86rm4rw2#

一种解决方法是用java编写一个助手方法,在这里它是明确的:

public class DimensionHelper {
    public static String getName(Dimension dimension) {
        return dimension.name;
    }
}

然后从Kotlin,你可以打电话 DimensionHelper.getName() 当你想访问 Dimension . 然后可以在kotlin中添加扩展方法:

fun Dimension.getName() = DimensionHelper.getName(this);

... 这样你就可以 Dimension.OVERWORLD.getName() .
这离理想还差得远,但它确实避免了用叉子叉东西。
(当然,我完全有可能不知道有一种Kotlin特有的方法可以做到这一点。)

相关问题