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