如何解决从kotlin调用的第三方Java库中的重载分辨率歧义
我在Kotlin中编写了一个小程序,它使用库https://github.com/KaptainWutax/SeedUtils,特别是Dimension枚举https://github.com/KaptainWutax/SeedUtils/blob/master/src/main/java/kaptainwutax/seedutils/mc/Dimension.java
当我打电话给PowerMockito.whenNew
,我得到B mock = Mockito.mock(B.class);
PowerMockito.whenNew(B.class).withAnyArguments().thenReturn(mock);
Mockito.when(mock.test()).thenReturn(2);
A obj=new A();
assertEquals(obj.test(),2);
。
我知道是什么问题,问题是Dimension.OVERWORLD.name
有Overload resolution ambiguity
字段,而枚举类本身有enum Dimension
字段https://kotlinlang.org/docs/reference/enum-classes.html
问题是,我该怎么办。我当前的方法是派生该库以及我使用并依赖的所有其他4个库,将该枚举中的name
重命名为其他名称,但是我讨厌不得不派生5个存储库来重命名单个字段。
还有其他解决方法吗?我可以指定使用哪个名称吗?是否有一种方法可以通过告诉JVM做什么来消除这种歧义?
还是没有什么事情要做,而命名枚举字段name
是使Kotlin无法使用的有效方法吗?
解决方法
一种解决方法是在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特定的方式可以做到这一点。)
,在@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]!!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。