这是我的情况:
trait BPO
trait BBO
class PointBO extends BBO
class PointPO extends BPO
class CircleBO extends BBO
class CirclePO extends BPO
trait Mapper[-P <: BPO,+B <: BBO] {
def mapAsBBO(bpo: P): B
}
class PointMapper extends Mapper[PointPO,PointBO]{
override def mapAsBBO(bpo: PointPO): PointBO = {
println("Construct point")
new PointBO
}
}
class CircleMapper extends Mapper[CirclePO,CircleBO] {
override def mapAsBBO(bpo: CirclePO): CircleBO = {
println("Construct circle")
new CircleBO
}
}
class Registry{
def method[P,B](po:P,bo:B)(implicit mapper: Mapper[P,B]) = mapper.mapAsBBO(po)
}
val r = new Registry
val s = r.method[PointPO,PointBO](new PointPO,new PointBO)
我想传递给方法method
,只是涉及映射的两个类,让Scala类型推断为我实现正确的映射器,是否可能?
我收到此错误:
错误:(31,40)找不到参数映射器的隐含值:A $ A191.this.Mapper [A $ A191.this.PointPO,A $ A191.this.PointBO] lazy val s = r.method [PointPO,PointBO](新PointPO,新PointBO) ^
对我来说另一种方式应该没问题,将其称为方法method
只传递mapper类:
val s = r.method[PointMapper](new PointPO,new PointBO)
这是完成这条街之一的任何方式,如果其中一条比另一条更好,还有一点解释。
修改
在原点我想制作具有两个参数协变的特征Mapper:
trait Mapper[+P <: BPO,+B <: BBO] {
def mapAsBBO(bpo: P): B
}
就像下面的任务一样:
val d:Mapper[BPO,BBO] = new CircleMapper()
但编译器抱怨我必须是conovariant的P参数
还有另一种解决方案吗?
问候。
答案 0 :(得分:1)
首先,在您的代码中,隐式映射器丢失(如异常中所述)。
所以我在下面添加了这些内容。 除此之外,如果您为映射器添加隐式值,则会出现类型边界问题,因为该方法需要与Mapper相同的类型边界,因此我也对此进行了调整:
trait BPO
trait BBO
class PointBO extends BBO
class PointPO extends BPO
class CircleBO extends BBO
class CirclePO extends BPO
trait Mapper[P <: BPO,B <: BBO] {
def mapAsBBO(bpo: P): B
}
class PointMapper extends Mapper[PointPO,PointBO]{
override def mapAsBBO(bpo: PointPO): PointBO = {
println("Construct point")
new PointBO
}
}
class CircleMapper extends Mapper[CirclePO,CircleBO] {
override def mapAsBBO(bpo: CirclePO): CircleBO = {
println("Construct circle")
new CircleBO
}
}
class Registry{
def method[P <: BPO,B <: BBO](po:P,bo:B)(implicit mapper: Mapper[P,B]) = mapper.mapAsBBO(po)
}
implicit val pMapper = new PointMapper()
implicit val cMapper = new CircleMapper()
val r = new Registry
r.method(new PointPO,new PointBO)
修改
从r.method
中删除了显式类型参数,因为它们是由编译器推断的。还删除了与Mapper类型参数的共同和反向差异,因为对于此功能,它不是必需的,并且没有给出关于它被使用的原因的进一步上下文,因此它只会导致混淆。
EDIT2
如果你没有理由实例化mapper类,你也可以将它们定义为隐式对象:
trait BPO
trait BBO
class PointBO extends BBO
class PointPO extends BPO
class CircleBO extends BBO
class CirclePO extends BPO
trait Mapper[P <: BPO,B <: BBO] {
def mapAsBBO(bpo: P): B
}
implicit object PointMapper extends Mapper[PointPO,PointBO]{
override def mapAsBBO(bpo: PointPO): PointBO = {
println("Construct point")
new PointBO
}
}
implicit object CircleMapper extends Mapper[CirclePO,CircleBO] {
override def mapAsBBO(bpo: CirclePO): CircleBO = {
println("Construct circle")
new CircleBO
}
}
class Registry{
def method[P <: BPO,B <: BBO](po:P,bo:B)(implicit mapper: Mapper[P,B]) = mapper.mapAsBBO(po)
}
val r = new Registry
r.method(new PointPO,new PointBO)