尝试使用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>
什么比铸造更优雅的解决方案才能使其编译?
答案 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.Double
和java.lang.Number
的常见超类型是java.lang.Number
,因此这是T
的推断类型}。
对f
的第二次调用有效,因为我们已明确告诉编译器T==java.lang.Number
。当编译器发现第二个参数0 : Int
与预期类型java.lang.Number
不匹配时,它会搜索从Int
到Number
的隐式转换。编译器找到Predef.int2Integer
并应用它。一切都很好。
第三次调用f
不起作用,因为第一个参数约束T == Number
,第二个参数说T >: Int
(即T
是Int
)的超类型。 Int
和Number
的常见超类型为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评论解释)