2

我有一个 F 有界类型,我的目标是创建一个类型参数化的方法以便能够重用它。这是示例代码:

trait FType {
  type ThisType <: FType

  def deepCopy(): ThisType

}

class ConcreteType extends FType {

  override type ThisType = ConcreteType

  override def deepCopy(): ConcreteType = this

}

class ConcreteType2 extends FType {

  override type ThisType = ConcreteType2

  override def deepCopy(): ConcreteType2 = this

}

object FType {

  def deepCopy[T <: FType](_type: T): T = {
    _type.deepCopy()
  }

/*  def deepCopy2(c: ConcreteType2): ConcreteType2 = {
    c.deepCopy()
  }*/

  def main(args: Array[String]): Unit = {
    //deepCopy2(new ConcreteType2)
  }

}

但是,代码无法编译。编译器抛出此错误:

Error:(29, 19) type mismatch;
 found   : _type.ThisType
 required: T
    _type.deepCopy()

我知道它与路径相关类型有关,因为_type.ThisType它与T.

但是,如果 F 有界类型与使用 F 有界类型的类型不完全相同,我该如何利用 F 有界类型呢?如果类型不完全相同,那是如何deepCopy2编译的?

注意:我知道我可以deepCopy通过对每个具体类型使用方法重载来避免使用类型参数。

4

2 回答 2

5

如果类型不完全相同,那么 deepCopy2 是如何编译的?

这很简单。它之所以有效,是因为不涉及多态性。静态知道ConcreteType2deepCopy()返回的方法ConcreteType2。您甚至可以type ThisType从整个层次结构中删除,它仍然可以以相同的方式工作。


但是,如果 F 有界类型与使用 F 有界类型的类型不完全相同,我该如何利用 F 有界类型呢?

您需要告诉编译器它是相同的,因为您没有指定足够的。让我们看一个有效且具有多态性的示例:

def deepCopy[A <: FType { type ThisType = A }](_type: A): A = _type.deepCopy()
//                      ^ --important bit-- ^

这定义了一个适用于任何对象的方法,A并且FType它的类型成员ThisType设置为A,将它们捆绑在一起。这意味着它适用于您对ConcreteTypeand的定义ConcreteType2。但是,对于未正确定义的类,它不会编译,例如:

class Bogus extends FType {
  override type ThisType = ConcreteType2
  override def deepCopy(): ConcreteType2 = new ConcreteType2
}

deepCopy(new Bogus)

或者,让我们从您的方法的略微修改版本开始:

def deepCopyPD[A <: FType](_type: A): _type.ThisType = _type.deepCopy()
                                   ^path-dependent^

它对 没有任何限制ThisType,但实际上编译器能够在所有情况下推断出它的正确版本:

val x: ConcreteType2 = deepCopyPD(new ConcreteType2)
val y: ConcreteType2 = deepCopyPD(new Bogus) // yep, this invocation is possible with such signature

但是,也可以使用类型相等证据作为隐式参数进一步添加约束:

def deepCopyPD2[A <: FType](_type: A)(implicit ev: _type.ThisType =:= A): A = _type.deepCopy()

这再次禁止调用Bogus

于 2018-11-26T12:50:24.400 回答
2

在 F 有界类型中,您通常将ThisType其作为类型参数而不是类型成员:

trait FType[ThisType <: FType] {
  def deepCopy(): ThisType    
}

class ConcreteType extends FType[ConcreteType] {
  override def deepCopy(): ConcreteType = this
}

// in object FType
def deepCopy[T <: FType[T]](_type: T): T = {
  _type.deepCopy()
}

注意区别:在FType.deepCopy编译器中知道返回类型_type.deepCopy()T.

可以对类型成员执行相同的操作:

def deepCopy[T <: FType { type ThisType <: T }](_type: T): T = 
  _type.deepCopy()
于 2018-11-26T12:43:43.103 回答