0

我正在学习 Scala 中的 F 绑定类型,并且遇到了一种我不知道出了什么问题的情况。

我做了三个测试,代码如下:

import scala.collection.mutable

def test1() = {

  trait Abstract {
    type ThisType <: Abstract
    def deepCopy(): ThisType
  }

  case class Concrete1(a: Int) extends Abstract {
    override type ThisType = Concrete1
    override def deepCopy(): ThisType = this.copy()

  }

  case class Concrete2(a: Int) extends Abstract {
    override type ThisType = Concrete2
    override def deepCopy(): ThisType = this.copy()

  }

  val set = new mutable.HashSet[Abstract]()

  set ++= List(Concrete1(1), Concrete2(2))

  val set2: mutable.Set[Abstract] = set.map(_.deepCopy())

}

def test2() = {

  trait Abstract {
    type ThisType
    def deepCopy(): ThisType
  }

  case class Concrete1(a: Int) extends Abstract {
    override type ThisType = Concrete1
    override def deepCopy(): ThisType = this.copy()

  }

  case class Concrete2(a: Int) extends Abstract {
    override type ThisType = Concrete2
    override def deepCopy(): ThisType = this.copy()

  }

  val set = new mutable.HashSet[Abstract]()

  set ++= List(Concrete1(1), Concrete2(2))

  val set2: mutable.Set[Abstract] = set.map(_.deepCopy())

}

def test3() = {


  trait Abstract[T <: Abstract[T]] {
    def deepCopy(): T
  }

  case class Concrete1(a: Int) extends Abstract[Concrete1] {
    override def deepCopy(): Concrete1 = this.copy()

  }

  case class Concrete2(a: Int) extends Abstract[Concrete2] {
    override def deepCopy(): Concrete2 = this.copy()

  }

  val set = new mutable.HashSet[Abstract[_]]()

  set ++= List(Concrete1(1), Concrete2(2))

  val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())

}

test1工作正常。test2 和 test3 产生编译时错误。

test2中,我省略了这ThisTypeAbstract. 我知道如果我不设置这个上限,ThisType可以是任何东西。但是如果我有一个SetofAbstract并且我执行了一个deepCopy()它的元素,它不会是同一类型吗?编译器产生此错误:

Error:(53, 45) type mismatch;
 found   : scala.collection.mutable.HashSet[Abstract#ThisType]
 required: scala.collection.mutable.Set[Abstract]
  val set2: mutable.Set[Abstract] = set.map(_.deepCopy())
                                           ^

我不明白为什么在这种情况下 (test2)与 test1 中Abstract#ThisType的类型不同。Abstract它与路径相关类型有关吗?如果是这样,解释是什么?

test3中,我尝试执行与 test1 中相同的操作,但使用类型参数,此编译器在行中抛出错误val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())

Error:(78, 48) type mismatch;
 found   : scala.collection.mutable.HashSet[Any]
 required: scala.collection.mutable.Set[Abstract[_]]
Note: Any >: Abstract[_], but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ >: Abstract[_]`. (SLS 3.2.10)
  val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())
                                              ^
Error:(140, 45) type mismatch;
 found   : scala.collection.mutable.HashSet[Abstract#ThisType]
 required: scala.collection.mutable.Set[Abstract]
  val set2: mutable.Set[Abstract] = set.map(_.deepCopy())
                                           ^
Error:(166, 48) type mismatch;
 found   : scala.collection.mutable.HashSet[Any]
 required: scala.collection.mutable.Set[Abstract[_]]
Note: Any >: Abstract[_], but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ >: Abstract[_]`. (SLS 3.2.10)
  val set2: mutable.Set[Abstract[_]] = set.map(_.deepCopy())
                                              ^

这与通配符有关,但我不知道如何声明没有通配符的此类类型。

4

1 回答 1

1

这是一个版本,显示了我的解释中的一些部分https://scalafiddle.io/sf/Wnk3ekK/2

因此,由于缺少界限,2 scalac 中的问题无法证明这Abstract是 typemeber 的常见超类型。看到ThisType可以是,例如Int,它确实不是的子类型,Abstract因此不符合条件Set[Abstract]

在 3 中是Abstract[_]存在的问题,它不能像那样工作,所以你可以插入一个常见的超类型,如图所示。

于 2018-11-21T10:21:54.423 回答