Open gavinking opened 10 years ago
I am having trouble because of this issue... I need to subclass some JavaFX classes and I can't do it in Ceylon! My latest example:
class CeylonListener<Prop>() satisfies ChangeListener<Prop> {
shared actual void changed(ObservableValue<Prop>? obs, Prop? old, Prop? newValue) {
}
}
name clash: changed(javafx.beans.value.ObservableValue<Prop>,Prop,Prop) in ceylonfx.binding.CeylonListener and changed(javafx.beans.value.ObservableValue<? extends T>,T,T) in javafx.beans.value.ChangeListener have the same erasure, yet neither overrides the other
Backend Error
@renatoathaydes try this:
Ceylon:
import javafx.beans.\ivalue {
ObservableValue
}
shared class Event<out T>(ObservableValue<T> observableValue) {
shared T observable => observableValue.\ivalue;
}
Java:
package ceylonfx.application.java;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
public abstract class Listener<T> implements ChangeListener<T> {
private static <X> Event<X> toEvent(ObservableValue<X> observableValue) {
return new Event<X>(null, observableValue);
}
public void changed(ObservableValue<? extends T> observable,
T oldValue,
T newValue) {
onChange(toEvent(observable), oldValue, newValue);
}
public abstract void onChange(Event<? extends T> observable,
T oldValue,
T newValue);
}
P.S. I had to enable "Java classes calling Ceylon" in the IDE project properties.
That sounds impossible in the general case, no? I mean, if in order to determine if a type parameter appears only in covariant location, we need to know if some places are covariant locations, which is infinite.
Moving to 1.2
Aw man, well at least do it for j.l.Class
and any other especially important cases in java.base
.
Detecting that a class is covariant is not hard, BTW, we already have code in the typechecker that could very easily be repurposed.
I think we should do this for 1.1.
Detecting that a class is covariant is not hard, BTW, we already have code in the typechecker that could very easily be repurposed.
Great; where?
Well, look at TypeArgumentVisitor
.
In this case: A
and B
are only covariant in T
if both are covariant. This accepts two solutions: that both are covariant, or none are. This doesn't sound at all like a tractable problem, or one for which you have code, since the typechecker doesn't do variance inference.
class A<T> {
public B<T> f(){ return null; }
}
class B<T> {
public A<T> f(){ return null; }
}
Otherwise, sure I can special-case java.lang.Class
for now if you want.
@FroMage Well, OK, that's a pretty good point. So sure, we would miss some cases, since we would have to assume that most container types are invariant (except for arrays). But surely we would still be able to detect quite a few Java types as covariant.
We explicitly made Java arrays invariant ;)
So I just noticed that
java.lang.Class
is actually a covariant type, though of course that is totally implicit. I suppose there's quite likely a bunch of other Java types like that. We should make the model loader detect Java types which are actually co-(or contra-)variant and add that information to the model.See this stack overflow question:
http://stackoverflow.com/questions/20241368/how-to-turn-a-ceylon-class-which-extends-a-java-class-into-the-java-class