使用Java参数化构造函数和参数化接口的Scala编译错误

时间:2011-08-05 11:08:07

标签: java scala javafx javafx-2

尝试使用Scala 2.8.1 / JavaFx 2.0 beta编译以下代码时

new KeyValue(circle.translateYProperty, random() * height)

我收到以下错误:

[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

然而这行编译得很好:

new KeyValue(circle.translateXProperty.asInstanceOf[WritableValue[Any]], random() * width)

我检查了 KeyValue 构造函数,它具有以下签名:

public <T> KeyValue(javafx.beans.value.WritableValue<T> tWritableValue, T t) { /* compiled code */ }

circle.translateXProperty 返回 DoubleProperty ,它实现了以下界面:

public interface WritableNumberValue extends javafx.beans.value.WritableValue<java.lang.Number>

什么比铸造更优雅的解决方案才能使其编译?

2 个答案:

答案 0 :(得分:5)

- 根据Exception和Blaisorblade的评论修改答案 -

你已经达到了Scala应用implicits的限制,而不是(只是)Scala-Java互操作问题。这是一个简化的例子,

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
  • 第一次调用f是有效的,因为java.lang.Doublejava.lang.Number的常见超类型是java.lang.Number,因此这是T的推断类型}。

  • f的第二次调用有效,因为我们已明确告诉编译器T==java.lang.Number。当编译器发现第二个参数0 : Int与预期类型java.lang.Number不匹配时,它会搜索从IntNumber的隐式转换。编译器找到Predef.int2Integer并应用它。一切都很好。

  • 第三次调用f不起作用,因为第一个参数约束T == Number,第二个参数说T >: Int(即TInt)的超类型。 IntNumber的常见超类型为Any,但这不起作用,因为Foo[T]T中不是协变的(换句话说,我们可以不要将Foo[Number]投射到Foo[Any])。这是编译器错误消息的要点。请注意,编译器不知道如何应用隐式转换,因为它不知道要转换为的T的特定类型。

您发布的JavaFX代码的一个奇怪之处是KeyValue class不是通用的,但它具有通用构造函数。有趣的是,这在Scala中可能不是 ,因此我无法(据我所知)明确约束Scala代码中的参数T。如果整个KeyValue类是通用的,那么您也可以编写

new KeyValue[Number](circle.translateYProperty, random() * height)

这相当于Exception发布的代码,因为编译器会推断double2Double转换。

答案 1 :(得分:4)

前几天我遇到了同样的问题。在尝试了不同的事情后,我最终得到了它。

new KeyValue(circle.translateYProperty, double2Double(random() * height))

(请参阅Blaisorblade评论解释)