首页 文章

带类型参数的Scala方法

提问于
浏览
1

这是我的情况:

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类型推断为我实现正确的映射器,是否可能?

我收到此错误:

Error:(31, 40) could not find implicit value for parameter mapper: A$A191.this.Mapper[A$A191.this.PointPO,A$A191.this.PointBO] lazy val s = r.method[PointPO,PointBO](new PointPO,new PointBO) ^

另一种方式对我来说应该没问题,将其称为方法 method 只传递mapper类:

val s = r.method[PointMapper](new PointPO,new PointBO)

这是完成这条街之一的任何方式,如果其中一条比另一条更好,还有一点解释 .

EDIT:

在原点我想制作具有两个参数协变的特征Mapper:

trait Mapper[+P <: BPO,+B <: BBO] {
  def mapAsBBO(bpo: P): B
}

这样下面的任务就好了:

val d:Mapper[BPO,BBO] = new CircleMapper()

但编译器抱怨我P参数必须是controvariant

还有另一种解决方案吗?

问候 .

1 回答

  • 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

    如果您没有理由实例化映射器类,您还可以将它们定义为隐式对象:

    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)
    

相关问题