When trying to compile the following code with Scala 2.8.1/JavaFx 2.0 beta
new KeyValue(circle.translateYProperty, random() * height)
I get the following error:
[error] found : javafx.beans.property.DoubleProperty
[error] required: javafx.beans.value.WritableValue[Any]
[error] new KeyValue(circle.translateYProperty, random() * height)
[error] ^
[error] one error found
Whereas this line gets compiled just fine:
new KeyValue(circle.translateXProperty.asInstanceOf[WritableValue[Any]], random() * width)
I checked the KeyValue constructor and it has the following signature:
public <T> KeyValue(javafx.beans.value.WritableValue<T> tWritableValue, T t) { /* compiled code */ }
circle.translateXProperty returns DoubleProperty which implements the following interface:
public interface WritableNumberValue extends javafx.beans.value.WritableValue<java.lang.Number>
What would be more elegant solution than casting to make it compile?
— Revised answer, based on Exception and Blaisorblade’s comments —
You’ve hit a limitation of Scala’s application of implicits, rather than (just) a Scala-Java interop problem. Here’s a simplified example,
The first call to
fworks because the common supertype ofjava.lang.Doubleandjava.lang.Numberisjava.lang.Number, so that is the type inferred forT.The second call to
fworks because we’ve explicitly told the compiler thatT==java.lang.Number. When the compiler finds the second argument,0 : Int, doesn’t match the expected typejava.lang.Number, it searches for an implicit conversion fromInttoNumber. The compiler findsPredef.int2Integerand applies it. All is well.The third call to
fdoesn’t work, because the first parameter constrainsT == Number, and the second argument saysT >: Int(that is,Tis a supertype ofInt). The common supertype ofIntandNumberisAny, but that won’t work becauseFoo[T]is not covariant inT(in other words, we can’t cast aFoo[Number]to aFoo[Any]). That’s the gist of the compiler’s error message. Note that the compiler doesn’t know how to apply an implicit conversion, because it doesn’t know a specific type ofTto convert to.One strange thing about the JavaFX code that you posted is that the
KeyValueclass is not generic, but is has a generic constructor. Interestingly, this is not possible in Scala, so there’s no way (as far as I can tell), to explicitly constrain the parameterTfrom Scala code. If the entireKeyValueclass were generic, you’d also be able to writewhich would be equivalent to the code that Exception posted, since the compiler would infer the
double2Doubleconversion.