我有一个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
中使用类型参数。
如果类型不完全相同,那么deepCopy2是如何编译的?
这很简单。它之所以有效,是因为不涉及多态性。静态已知ConcreteType2
具有返回ConcreteType2
的deepCopy()
方法。您甚至可以从整个层次结构中删除type ThisType
,它仍然可以以相同的方式工作。
但是,如果F有界类型与使用F有界型的类型不完全相同,我如何利用F有界的类型?
您需要告诉编译器它是一样的,因为您没有指定足够的。让我们来看看一个有效且多态的例子:
def deepCopy[A <: FType { type ThisType = A }](_type: A): A = _type.deepCopy()
// ^ --important bit-- ^
这定义了一个适用于FType
的任何A
的方法,并且它的类型成员ThisType
设置为A
,将它们绑定在一起。这意味着它适用于您对ConcreteType
和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
进行调用
在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()