![](/img/trans.png)
[英]Scala: deferring a trait method to an implicit class in parent trait's object
[英]In Scala, is it possible for parent trait to call method implemented in child class?
我正在使用Scala,想知道为什么此代码有效。
trait Base {
def foo(x: Int): Int
}
trait A extends Base {
def fooA(x: Int): Int = {
foo(x)
}
}
class Impl extends Base with A {
override def foo(x: Int): Int = x
}
val a = new Impl
a.fooA(10)
a.fooA(10)
的结果是10。
但是,在特征A
,方法fooA
使用的是在Impl
类中实现的foo
方法。
同样, Impl
类扩展了类A
(在类Impl
的声明中with A
)。
它不是圆形的吗?
这怎么可能?
谢谢。
这里没有什么特别的,方法foo是在trait中定义的,允许在impl中调用和实现它。 从何处调用它并不重要。
调用如下->调用fooA。 它仅在imp继承的A中定义。 fooA呼叫foo。 foo在trait中定义,实现在impl中出现。 这不是循环的,而是最基本的用法。
如果有多个实现(例如,在特征A中),则该顺序将基于线性化(请参阅https://stackoverflow.com/a/34243727/1547734 )
从编译的角度来看,一切都可以检出。 Base
要求任何人扩展foo
的实现,而Impl
就是这样做的。 特质A
被允许使用foo
因为它扩展了Base
。 一切都清楚了。
但是,我看到您的困惑。 我不会真的称其为循环。 它更像是在Impl
之前(在Impl
)使用某种东西( A
foo
)。 之所以可行,是因为您使用了def
。 编译器知道此值以后会可用(因为如果在其余的编译过程中找不到该值,它将中断),并且只是说“我知道在调用该值时该值将可用(给定)编译成功),并且它是一个def
,这意味着我将在那儿进行计算。因此,我现在不需要这样做。”
但是,如果使用val
,则foo
将在A
那一点被初始化,因此您将获得该初始值,对于Interegers而言该值为0:
trait Base {
val foo: Int
}
trait A extends Base {
val fooA: Int = foo
}
class Impl extends Base with A {
override val foo: Int = 42
}
val a = new Impl
println(a.fooA) // prints 0 although we wanted 42
请注意, lazy val
与def
具有相同的效果(它也是lazy计算的,只是在第一次使用时它只会被计算一次),因此修改上面的代码以override lazy val foo: Int = 42
将导致在打印42。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.