2

假设您在需要使用的遗留库中有一个 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>?
4

1 回答 1

2

不幸的是,在这种情况下,您需要回到 Java 来添加一些胶水。今天,你不能完全用锡兰写出来。

解释

问题在于,由于 Ceylon 没有使用站点协变,并且由于 Ceylon 类型检查器甚至不了解Java的使用站点协变,因此类型检查器处理此方法:

public void takeClass(Class<? extends JavaClass> cls);

好像它有这个更严格的签名:

public void takeClass(Class<JavaClass> cls);

此外,类型检查器将所有 Java 类视为不变类型。

因此,由于javaClass<CeylonClass>()产生 a Class<CeylonClass>,它不被认为可分配给参数 of takeClass()。:-(

解决方法

解决方法是添加以下 Java 方法:

public static <T extends JavaClass> void takeClass2(Class<T> cls) {
    takeClass(cls);
}

现在这个方法可以像这样从 Ceylon 调用:

javaThing.takeClass2( javaClass<CeylonClass>() );

高温高压

附言

在写这篇文章时,我注意到它实际上java.lang.Class一种协变类型,我认为 Ceylon 也应该很容易注意到这一点。所以我创建了这个问题:

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

于 2013-11-28T03:49:18.367 回答