2011-08-05 27 views
4

當試圖使用Scala 2.8.1/2.0了JavaFx公測編譯下面的代碼與Java Scala的編譯錯誤參數化的構造和參數化界面

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) 

我查了鍵值構造函數,它具有以下特徵:

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

你試過明確指定類型? 'new KeyValue [Any](circle ...)' – agilesteel

+0

是的,我試過這個,但它說_KeyValue不採取類型parameters_(類_KeyValue_不參數化,只有構造函數) – Stas

+1

另外我不認爲這會改變任何東西 - 從錯誤信息中你可以看到編譯已經推斷出'Any'作爲'T'的邊界。 –

回答

5

- 修訂的答案,基於異常和Blaisorblade的評論 -

你已經打implicits Scala的應用程序的限制,而不是(只)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) 

這將相當於異常發佈的代碼,因爲編譯器會推斷double2Double轉換。

+0

謝謝,這聽起來很合理! – Stas

+1

我重寫了我的答案,因爲我原來的錯誤。 –

3

幾天前我有同樣的問題。嘗試不同的事情後,我結束了。

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

(見解釋Blaisorblade評論)

+0

我很想嘗試解決方案,但不是解釋。我認爲問題可能與類型推斷有關 - 類型參數T被推斷爲Any(如錯誤消息所示),因此不需要在其中應用隱式轉換,因此不會應用轉換。 – Blaisorblade

+0

這是一個好點,我可能應該指出,它只是一個假設。我仍然試圖找出導致問題的原因。但我想知道爲什麼它的工作原理,如果你給它一個java.lang.Double,如果它與T被推斷爲任何 – lucidd

+2

有關。一個問題是,java.lang.Number和scala.Double的通用超類型是Any - if您將後者更改爲java.lang.Double,常見的超類型爲java.lang.Number。不知道爲什麼任何推斷雖然,除非WritableValue被認爲是協變(但我認爲它不是,給出錯誤)。 – Blaisorblade