Skip to main content
 首页 » 编程设计

ceylon中如何将扩展 Java 类的 Ceylon 类转换为 Java 类

2024年11月01日8tintown

假设您需要使用旧库中有一个 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 也应该很容易注意到这一点。所以我创建了这个问题:

https://github.com/ceylon/ceylon-compiler/issues/1474