[英]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.