如何在父类中定义返回类型,使其与子实例类匹配?
在下面的例子中,需要定义echo函数,使其返回调用this的子类的对象。
trait A[T] {
def echo(a: T): T
}
class B extends A[B] {
override def echo(x: B):B = x
}
class C extends B {
def repeat(x: B): B = echo(x)
}
val b = new B()
val c = new C()
// Fails with error value repeat is not a member of B
c.repeat(b).repeat(b)
// Compilation error
// Found: B
// Required: D
class D extends B {
def repeat(x: B): D = echo(x)
}
}
你到底想干什么?
如果您跟踪调用链,您将看到c.repeat(b)
返回b:B
的实例,该实例显然没有repeat
方法,该方法在C
中定义。
换句话说,在代码中,b.echo(x:B)
返回x
,而不是this
!
也许你想从C.repeat
返回this
?这应该可以工作:
class C extends B {
def repeat(x: B): C = {
echo(x)
this
}
}
val b = new B()
val c = new C()
c.repeat(b).repeat(b)
正如@Aivean所提到的,您的方法repeat
是在类C
上定义的,并返回其父类B
的实例,该实例没有repeat
方法。
val tmpB = c.repeat(b) // tmpB is an instance of B
tmpB.repeat(b) // fail cuz B has no "repeat" method
。现在回答主要问题:"如何使父类返回一个可以匹配子类型的类型?">
与trait A相同,但对其参数类型增加了约束,因此T必须是A:
trait A[T<:A[T]]
class B extends A[B]
阅读更多关于"f界多态"在这个伟大的答案:https://stackoverflow.com/a/21699765/1206998