Scala类型和F有界类型

时间:2018-11-21 09:27:23

标签: scala f-bounded-polymorphism

我正在学习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可以是任何东西。但是,如果我有一个Set的一个Abstract并执行了一个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)Abstract#ThisTypeAbstract的类型不同,而在test1中却是这样。它与路径相关类型有关吗?如果是这样,解释是什么?

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())
                                              ^

这与通配符有关,但是我不知道如何在没有通配符的情况下声明此类。

1 个答案:

答案 0 :(得分:1)

这里有一个版本,显示了我的解释https://scalafiddle.io/sf/Wnk3ekK/2

中的某些部分

因此2 scalac中的问题不能证明Abstract由于缺少边界而成为类型成员的常见超类型。看到ThisType可以例如是Int,它实际上不是Abstract的子类型,因此没有资格加入Set[Abstract]

3中的

问题是Abstract[_]是存在的,并且不能像那样工作,因此您可以插入所示的公共超类型。