在变元和返回位置具有类型参数的F-有界类型和方法



我有一个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.ThisTypeT不是同一类型。

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

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

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

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


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

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

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

这定义了一个适用于FType的任何A的方法,并且它的类型成员ThisType设置为A,将它们绑定在一起。这意味着它适用于您对ConcreteTypeConcreteType2的定义。然而,对于没有正确定义的类,它不会编译,比如这个:

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进行调用

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

最新更新