假设您需要使用旧库中有一个 Java 方法,该方法采用 Class 作为参数:
public void takeClass(Class<? extends JavaClass> cls);
现在,假设您有一个扩展 JavaClass 的 Ceylon 类:
shared class CeylonClass() extends JavaClass() {}
现在,我该如何使用方法takeClass
在 ceylon 这样行得通吗?
javaThing.takeClass( `class CeylonClass` );
// or maybe this should work?
javaThing.takeClass( javaClass<CeylonClass>() );
如上所示,我一直在尝试函数javaClass
在模块 ceylon.interop.java
没有成功...如果我这样做javaClass<JavaClass>()
然后它就可以工作了,但这当然对我来说没有用。
编辑:
使用 javaClass<CeylonClass>()
时遇到的错误如上图:
argument must be assignable to parameter class of takeClass:
Class<CeylonClass> is not assignable to Class<JavaClass>?
请您参考如下方法:
不幸的是,在这种情况下您需要返回到 Java 来添加一些粘合剂。今天你无法完全用 ceylon 来写它。
说明
问题是,由于 Ceylon 没有使用站点协方差,并且 Ceylon 类型检查器甚至不理解 Java 的使用站点协方差,因此类型检查器会处理此方法:
public void takeClass(Class<? extends JavaClass> cls);
就好像它有这个更具限制性的签名:
public void takeClass(Class<JavaClass> cls);
此外,类型检查器将所有 Java 类视为不变类型。
因此,自 javaClass<CeylonClass>()
产生 Class<CeylonClass>
,它不被视为可分配给 takeClass()
的参数。 :-(
解决方法
解决方法是添加以下 Java 方法:
public static <T extends JavaClass> void takeClass2(Class<T> cls) {
takeClass(cls);
}
现在这个方法可以从 ceylon 像这样调用:
javaThing.takeClass2( javaClass<CeylonClass>() );
HTH
附注
在写这篇文章时,我注意到事实上 java.lang.Class
实际上是一种协变类型,我认为 Ceylon 也应该很容易注意到这一点。所以我创建了这个问题: