Scala 类型不匹配:需要 _$1,其中类型 _$1 <:
Scala type mismatch: required _$1 where type _$1 <:
我是 Scala 的新手,我遇到了一个我无法理解和解决的问题。我写了一个通用的 trait
就是这个:
trait DistanceMeasure[P<:DbScanPoint] {
def distance(p1:P, p2:P):Double
}
其中 DbScanPoint
就是:
trait DbScanPoint extends Serializable {}
然后我有以下两个 classes 扩展它们:
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:
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: _ where type _ <: it.polito.dbdmg.ontic.point.DbScanPoint
我不明白是哪个问题。我对其他 classes 做了非常相似的事情,但我没有出错,所以这个错误的原因对我来说很模糊。
有人可以帮助我吗?
谢谢。
更新
我通过将代码更改为:
设法完成了我需要的操作
trait DistanceMeasure {
def distance(p1:DbScanPoint, p2:DbScanPoint):Double
}
并且显然进行了所有相关更改。
你的问题的核心是你用一个存在类型定义你的 distanceMeasure
var,所以编译器不完全知道该类型。然后,您正在调用 distance
,这是将两个 P <: DbScanPoint
类型的实例传入两个 Point2d
实例。现在,这些是 distanceMeasure
后面的具体 class 的正确类型(一个新的 EuclideanDistance
),但是您定义 distanceMeasure
的方式(具有存在性),编译器无法强制 Point2d
实例是具体底层 DistanceMeasure
所采用的正确类型。
出于争论的缘故,你不是使用新的 EuclideanDistance
,而是实例化了一个完全不同的 DistanceMeasure
实现,它没有使用 Point2d
个实例,然后尝试调用 distance
他就是你在这里拥有它的方式。如果编译器不能强制底层 class 接受提供的参数,它会这样抱怨。
有很多方法可以解决这个问题,解决方案最终取决于您在 class 结构中需要的灵活性。一种可能的方式是这样的:
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))
但是如果我没有真正理解您对所需抽象级别的要求,则由您来定义重组。
我是 Scala 的新手,我遇到了一个我无法理解和解决的问题。我写了一个通用的 trait
就是这个:
trait DistanceMeasure[P<:DbScanPoint] {
def distance(p1:P, p2:P):Double
}
其中 DbScanPoint
就是:
trait DbScanPoint extends Serializable {}
然后我有以下两个 classes 扩展它们:
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:
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: _ where type _ <: it.polito.dbdmg.ontic.point.DbScanPoint
我不明白是哪个问题。我对其他 classes 做了非常相似的事情,但我没有出错,所以这个错误的原因对我来说很模糊。
有人可以帮助我吗?
谢谢。
更新
我通过将代码更改为:
设法完成了我需要的操作trait DistanceMeasure {
def distance(p1:DbScanPoint, p2:DbScanPoint):Double
}
并且显然进行了所有相关更改。
你的问题的核心是你用一个存在类型定义你的 distanceMeasure
var,所以编译器不完全知道该类型。然后,您正在调用 distance
,这是将两个 P <: DbScanPoint
类型的实例传入两个 Point2d
实例。现在,这些是 distanceMeasure
后面的具体 class 的正确类型(一个新的 EuclideanDistance
),但是您定义 distanceMeasure
的方式(具有存在性),编译器无法强制 Point2d
实例是具体底层 DistanceMeasure
所采用的正确类型。
出于争论的缘故,你不是使用新的 EuclideanDistance
,而是实例化了一个完全不同的 DistanceMeasure
实现,它没有使用 Point2d
个实例,然后尝试调用 distance
他就是你在这里拥有它的方式。如果编译器不能强制底层 class 接受提供的参数,它会这样抱怨。
有很多方法可以解决这个问题,解决方案最终取决于您在 class 结构中需要的灵活性。一种可能的方式是这样的:
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))
但是如果我没有真正理解您对所需抽象级别的要求,则由您来定义重组。