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,
class Foo[T]
def f[T](x: Foo[T], y: T): T = y
f(new Foo[Number], new java.lang.Double(0)) // OK; infers T==Number
f[Number](new Foo[Number], 0) // OK; uses implicit int2Integer(0)
// f(new Foo[Number], 0) // error
The first call to f works because the common supertype of java.lang.Double and java.lang.Number is java.lang.Number, so that is the type inferred for T.
The second call to f works because we've explicitly told the compiler that T==java.lang.Number. When the compiler finds the second argument, 0 : Int, doesn't match the expected type java.lang.Number, it searches for an implicit conversion from Int to Number. The compiler finds Predef.int2Integer and applies it. All is well.
The third call to f doesn't work, because the first parameter constrains T == Number, and the second argument says T >: Int (that is, T is a supertype of Int). The common supertype of Int and Number is Any, but that won't work because Foo[T] is not covariant in T (in other words, we can't cast a Foo[Number] to a Foo[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 of T to convert to.
One strange thing about the JavaFX code that you posted is that the KeyValue class 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 parameter T from Scala code. If the entire KeyValue class were generic, you'd also be able to write
new KeyValue[Number](circle.translateYProperty, random() * height)
which would be equivalent to the code that Exception posted, since the compiler would infer the double2Double conversion.
I had the same problem a few days ago. After trying different things i ended up with that.
new KeyValue(circle.translateYProperty, double2Double(random() * height))
(see Blaisorblade comments for explanation)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With