Question

Suppose you have a Java method in a legacy library you need to use that takes a Class as an argument:

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

Now, suppose you have a Ceylon class which extends JavaClass:

shared class CeylonClass() extends JavaClass() {}

Now, how can I use the method takeClass in Ceylon such that this works?

javaThing.takeClass( `class CeylonClass` );

// or maybe this should work?
javaThing.takeClass( javaClass<CeylonClass>() );

As shown above, I've been trying function javaClass in module ceylon.interop.java without success... if I do javaClass<JavaClass>() then it works, but this is no use for me, of course.

EDIT:

The error I get when using javaClass<CeylonClass>() as shown above:

argument must be assignable to parameter class of takeClass:
Class<CeylonClass> is not assignable to Class<JavaClass>?
Was it helpful?

Solution

Unfortunately, this is a case where you need to drop back to Java to add some glue. You can't, today, write it completely in Ceylon.

Explanation

The problem is that since Ceylon doesn't have use-site covariance, and since the Ceylon typechecker doesn't even understand Java's use-site covariance, the typechecker treats this method:

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

As if it had this more restrictive signature:

public void takeClass(Class<JavaClass> cls);

Furthermore, the typechecker treats all Java classes as if they were invariant types.

Therefore, since javaClass<CeylonClass>() produces a Class<CeylonClass>, it's not considered assignable to the parameter of takeClass(). :-(

Workaround

The workaround is to add the following Java method:

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

Now this method can be called like this from Ceylon:

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

HTH

P.S.

While writing this up, I noticed that in fact java.lang.Class is actually a covariant type, and I think that Ceylon should easily be able to notice that too. So I created this issue:

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top