如何使父类返回可以匹配子类型的类型?
Posted
技术标签:
【中文标题】如何使父类返回可以匹配子类型的类型?【英文标题】:How to make a parent class return a type which can match subtypes? 【发布时间】:2021-10-28 23:50:31 【问题描述】:如何在父类中定义返回类型以匹配子实例类?
在下面的示例中,需要定义 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)
【问题讨论】:
这是一个常见问题解答:docs.scala-lang.org/tutorials/FAQ/… 【参考方案1】:你到底想做什么?
如果你跟踪你的调用链,你会看到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)
【讨论】:
【参考方案2】:正如@Aivean 提到的,您的方法repeat
是在类C
上定义的,并返回其父类B
的实例,该实例没有repeat
方法。
所以你不能像这样调用 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-bounded polymorphism”的信息:https://***.com/a/21699765/1206998
【讨论】:
以上是关于如何使父类返回可以匹配子类型的类型?的主要内容,如果未能解决你的问题,请参考以下文章
MS 访问错误。 3464,过滤器类型不匹配,如何正确设置过滤器?