2013-02-20 80 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