Scala类型不匹配:需要_ $ 1其中type _ $ 1<:

时间:2015-03-07 14:11:01

标签: scala generics type-mismatch

我是Scala的新手,我面临着一个我无法理解和解决的问题。我写了一个通用的trait就是这个:

trait DistanceMeasure[P<:DbScanPoint] {
  def distance(p1:P, p2:P):Double
}

其中DbScanPoint只是:

trait DbScanPoint extends Serializable {}

然后我有以下两个类扩展它们:

class Point2d (id:Int, x:Double, y:Double) extends DbScanPoint {
   def getId() = id
   def getX() = x
   def getY() = y
}

class EuclideanDistance extends DistanceMeasure[Point2d] with Serializable {

   override def distance(p1:Point2d,p2:Point2d) = {
      (p1.getX()-p2.getX())*(p1.getX()-p2.getX()) + (p1.getY()-p2.getY()) * (p1.getY()-p2.getY())
  }
}

最后我有这堂课:

class DBScanSettings {

   var distanceMeasure:DistanceMeasure[_<:DbScanPoint] = new EuclideanDistance
   //...
}

我的问题是,如果我在我的测试主要写这个:

 val dbScanSettings = new DBScanSettings()
 dbScanSettings.distanceMeasure.distance(new Point2d(1,1,1), new Point2d(2,2,2))

我收到以下编译错误:

 type mismatch;
 [error]  found   : it.polito.dbdmg.ontic.point.Point2d
 [error]  required: _$1 where type _$1 <: it.polito.dbdmg.ontic.point.DbScanPoint

我无法理解哪个是问题所在。我和其他类做了非常类似的事情,我没有错误,所以这个错误的原因对我来说是非常模糊的。

是的,有人能帮助我吗?

感谢。

更新

我设法通过将代码更改为:

来完成我需要的操作
trait DistanceMeasure {
  def distance(p1:DbScanPoint, p2:DbScanPoint):Double
}

显然做了所有相关的改变。

1 个答案:

答案 0 :(得分:1)

问题的核心在于您使用存在类型定义distanceMeasure var,因此编译器不能完全知道该类型。然后,您正在调用distance,它将在两个P <: DbScanPoint实例中传递两个类型为Point2d的实例。现在,这些是distanceMeasure(一个新的EuclideanDistance)后面的具体类的正确类型,但是您定义distanceMeasure(具有存在性)的方式,编译器无法强制执行Point2d 1}}实例是DistanceMeasure所具体的具体类型。

为了论证而不是新的EuclideanDistance,您反而实例化了一个完全不同的DistanceMeasure impl,它没有采用Point2d个实例然后尝试调用distance你在这里拥有它。如果编译器不能强制执行基础类接受所提供的参数,那么它会像这样抱怨。

有很多方法可以解决这个问题,解决方案最终取决于您在类结构中所需的灵活性。一种可能的方式是这样的:

trait DBScanSettings[P <: DbScanPoint] {
  val distanceMeasure:DistanceMeasure[P]
 //...
}

class Point2dScanSettings extends DBScanSettings[Point2d]{
  val distanceMeasure = new EuclideanDistance
}

然后测试:

val dbScanSettings = new Point2dScanSettings()
dbScanSettings.distanceMeasure.distance(new Point2d(1,1,1), new Point2d(2,2,2))

但如果没有我真正理解您对所需抽象级别的要求,那么您需要定义重组。