2013-02-20 109 views
1

陌生感,我碰到這種類型不匹配,我不明白:Scala和泛型

error: type mismatch; 
found : org.fluentlenium.core.domain.FluentList[_<:org.fluentlenium.core.domain.FluentWebElement] 
required: org.fluentlenium.core.domain.FluentList[?0(in value $anonfun)] where type ?0(in value $anonfun) <: org.fluentlenium.core.domain.FluentWebElement 
Note: org.fluentlenium.core.domain.FluentWebElement >: ?0, but Java-defined class FluentList is invariant in type E. 
You may wish to investigate a wildcard type such as `_ >: ?0`. (SLS 3.2.10) 

事實上,它是一種高精度的「發現」值類型:

org.fluentlenium.core.domain.FluentList[_<:org.fluentlenium.core.domain.FluentWebElement] =>變體類型參數

我無法表示像這樣的情況,其中「找到」值是變體類型參數。我想這個簡單的代碼片段:

public class CarList<E extends Car> implements Collection<E> { // written in Java 
    //overriden methods from Collection here 
} 

public class Car{} // written in Java 

public Ferrari extends Car{} //written in Java 

object Main extends App { 

    val carList: CarList[Car] = new CarList[Car] 

    val l: CarList[Ferrari] = carList 

} 

編譯錯誤發生的歷史很相似:

error: type mismatch; 
found : app.CarList[app.Car]  //but in this case, logically it's an invariant type: Car 
required: app.CarList[app.Ferrari] 
Note: app.Car >: app.Ferrari, but Java-defined class CarList is invariant in type E. 
You may wish to investigate a wildcard type such as `_ >: app.Ferrari`. (SLS 3.2.10) 
val l: CarList[Ferrari] = carList 
            ^

如何修改我的代碼段結束正好與:

  • 同類錯誤比FluentList的錯誤(在「找到」值中精確變型類型參數):
    found : app.CarList[_ :> app.Car]
  • 從編譯器同樣的忠告:
    You may wish to investigate a wildcard type such as _ >:

,這樣我可以找出可能是問題的由來?

+0

試過簡單的'新FluentList [FluentWebElement]'?介意粘貼FluentList構造函數簽名? – pedrofurla 2013-02-20 12:37:31

+0

@pedrofurla是的,當然它會解決問題,但我試圖理解像這樣的問題的真正原因:)'FluentList'是用Java編寫的,構造函數的簽名是:'FluentList(java.util。收藏 listFiltered)' – Mik378 2013-02-20 12:42:15

+0

我明白了,您的疑問實際是關於類型差異。 – pedrofurla 2013-02-20 14:07:30

回答

0

在你的java例子中,你似乎顛倒了兩件事。您不能將一輛汽車列表分配到法拉利列表中。

考慮到這一點我解釋的網頁摘要:

class CarList[E <: Car] 

class Car 
class Ferrari extends Car 

object Main extends App { 

    val carList = new CarList[Ferrari] 

    // this now throws a compiler error 
    val l: CarList[Car] = carList 
} 

編譯器錯誤如下:

type mismatch; 
found: CarList[Ferrari] required: CarList[Car] 
Note: Ferrari <: Car, but class CarList is invariant in type E. 
You may wish to define E as +E instead. 

所以編譯器實際上幫助我們。這樣的定義:

class CarList[E <: Car] 

告訴我們的東西,延長Car列表中的編譯器。

但是,這並不告訴編譯器,CarList[Ferrari]也延伸CarList[Car]。爲了告訴編譯器,我們需要使E+共變。

因此解決了錯誤,我們可以做兩件事情:

  1. 定義CarListCarList[+E],說你不關心什麼是在他們,但如果A延伸B然後CarList[A]可以考慮延長CarList[B]
  2. CarList定義爲CarList[+E <: Car],與1相同,但與E的類型有額外的約束,因爲它必須是Car

This question about variance可能會提供更多信息。

+0

對不起,但我的問題不是:「如何解決它?」因爲我很好掌握協變/逆變。我的問題是:「如何修改我的代碼片段,以完全相同類型的錯誤?」,這意味着我想碰到一個錯誤通知:「found:'app.CarList [_ <:app.Car] //我想碰到這一行 必需:app.CarList [app.Ferrari] 注意:app.Car>:app.Ferrari,但是Java定義的類CarList在類型E中是不變的。 您可能希望調查通配符類型,如'_>:app.Ferrari'。(SLS 3.2.10)' 我想看到一個帶有變量參數的「found」::' – Mik378 2013-02-20 22:17:34

+0

你是完全正確的。有趣的問題雖然! – EECOLOR 2013-02-20 22:35:00

+0

沒問題:)我花了整整一天尋找一個解釋...我看不到一個:( – Mik378 2013-02-20 22:38:25