不变类型的混合 - 类型不匹配发现了其他一些

时间:2015-05-06 19:53:13

标签: scala

在下面的代码中,我在下面的“问题”行中收到了上述错误。我的问题是,是否可以为z设置变量声明,以便可以为x或y分配。我的解决方法是consumeProduce方法,我真的不想要。感谢您的投入!

package org.rest.rest

trait Common

case class A() extends Common
case class B() extends Common

trait Producer[T <: Common] {
  def produce(name: String): T = ???
}

trait Consumer[T <: Common] {
  def consume(t: T): Unit = { }
}

class ProducerConsumer[T <: Common] extends Producer[T] with Consumer[T]    {
 // don't really want this method
  def consumeProduce(name: String): Unit =
    consume(produce(name))
}

object DemoMI {

  val x = new ProducerConsumer[A]
  x.consume(x.produce("abc"))
  val y = new ProducerConsumer[B]
  y.consume(y.produce("abc"))
  val z: ProducerConsumer[_] = x // what type declaration for z is possible here?
  z.consume(z.produce("abc")) // problem
  z.consumeProduce("abc") // works

}

2 个答案:

答案 0 :(得分:1)

问题是Scala编译不知道z.consume采用z.produce生成的内容。

您可以使用抽象类型成员来解决此问题:

trait Producer {
  type T <: Common
  def produce(name: String): T = ???
}

trait Consumer {
  type T <: Common
  def consume(t: T): Unit = { }
}

trait ProducerConsumer extends Producer with Consumer

object DemoMI {
  val x = new ProducerConsumer {
    type T = A
    // definitions of consume and produce
  }

  val z: ProducerConsumer = x

  z.consume(z.produce("abc"))
}

抽象类型成员提升了所谓的路径依赖类型的概念。在上面的示例中,z.produce(...)的类型为z.T。另一方面,z.consume(...)采用z.T类型的值。虽然编译器不知道所涉及的具体类型,但它知道两种方法都具有兼容的类型,因此很乐意编译。

答案 1 :(得分:0)

是的,@ gzm0有解决方案。我确实尝试过抽象类型成员,但无法使它们与参数化特征的行为不同。我现在能够添加的进一步改进是将效果结合起来:

  trait ProducerConsumer extends Producer with Consumer 

  abstract class AbstractProducerConsumer[TT <: Common] extends ProducerConsumer {
    type T = TT
  }

  val x = new AbstractProducerConsumer[A] {}
  x.consume(x.produce("abc"))
  val y = new AbstractProducerConsumer[B] {}
  y.consume(y.produce("abc"))
  val z1: ProducerConsumer = x
  z1.consume(z1.produce("abc"))
  val z2: ProducerConsumer = y
  z2.consume(z2.produce("abc"))