Generics Scala类型不匹配错误

Generics Scala类型不匹配错误,generics,scala,Generics,Scala,我有一个导致类型不匹配的场景,我似乎无法解决。下面是代码的简化版本: abstract class Msg trait Channel[M <: Msg] { def receive(): M def ack(envelope: M) } object ChannelSender { private var channel : Channel[_ <: Msg] = _ def assignChannel(channel : Channel[_ <: Msg

我有一个导致类型不匹配的场景,我似乎无法解决。下面是代码的简化版本:

abstract class Msg

trait Channel[M <: Msg] {
  def receive(): M
  def ack(envelope: M)
}

object ChannelSender {
  private var channel : Channel[_ <: Msg] = _
  def assignChannel(channel : Channel[_ <: Msg]) = this.channel = channel

  def test() {
    val msg = channel.receive()
    channel.ack(msg) // Type mismatch here
  }
}

我可以让它在Scala 2.9下编译,只需做两个修改

trait Channel[M <: Msg] {
  type M2 = M       // Introduce a type member that's externally visible
  def receive(): M2
  def ack(envelope: M2)
}

object ChannelSender {
  private var channel : Channel[_ <: Msg] = _
  def assignChannel(channel : Channel[_ <: Msg]) = this.channel = channel

  def test() {
    val c = channel  // An immutable value, so that c.M2 is stable
    val msg = c.receive()
    c.ack(msg)       // OK now
  }
}

第一个更改是使用一个不可变的值val c=channel,因此依赖路径的类型c.M2始终表示相同的含义。第二个变化是在特征通道中引入类型成员类型M2=M。我不完全确定为什么这是必要的,可能是个bug吗?。需要注意的一点是,c.M2是一个有效类型,而c.M是未定义的。

我可以在Scala 2.9下编译它,只需做两个更改

trait Channel[M <: Msg] {
  type M2 = M       // Introduce a type member that's externally visible
  def receive(): M2
  def ack(envelope: M2)
}

object ChannelSender {
  private var channel : Channel[_ <: Msg] = _
  def assignChannel(channel : Channel[_ <: Msg]) = this.channel = channel

  def test() {
    val c = channel  // An immutable value, so that c.M2 is stable
    val msg = c.receive()
    c.ack(msg)       // OK now
  }
}

第一个更改是使用一个不可变的值val c=channel,因此依赖路径的类型c.M2始终表示相同的含义。第二个变化是在特征通道中引入类型成员类型M2=M。我不完全确定为什么这是必要的,可能是个bug吗?。需要注意的是,c.M2是一个有效类型,而c.M是未定义的。

好东西,谢谢!我不明白为什么这两个改变都是必要的。如果Channel.M在外部不可见,那么它有什么好处?我们是否总是必须为类型参数创建一个类型别名,以便在trait/类之外使用?对于ChannelSender的更改,路径依赖类型c.M2是否意味着相同的事情,因为我在同一个通道对象上调用receive和ack?好问题。对于第一个问题,我不知道答案。也许邮件列表上更了解情况的人能帮上忙。对于第二个问题,我同意Scala可以发现在这种情况下通道对象是不变的,但我假设Scala通常会简化假设,即变量不受信任,以保持不变。好东西,谢谢!我不明白为什么这两个改变都是必要的。如果Channel.M在外部不可见,那么它有什么好处?我们是否总是必须为类型参数创建一个类型别名,以便在trait/类之外使用?对于ChannelSender的更改,路径依赖类型c.M2是否意味着相同的事情,因为我在同一个通道对象上调用receive和ack?好问题。对于第一个问题,我不知道答案。也许邮件列表上更了解情况的人能帮上忙。对于第二种情况,我同意Scala可以发现在这种情况下通道对象是不变的,但我假设Scala通常会简化假设,即变量不受信任,从而保持不变。