我是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
}
显然做了所有相关的改变。
答案 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))
但如果没有我真正理解您对所需抽象级别的要求,那么您需要定义重组。