簡體   English   中英

在Scala中,父特征是否可以調用在子類中實現的方法?

[英]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 ,則fooA那一點被初始化因此您將獲得該初始值,對於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 valdef具有相同的效果(它也是lazy計算的,只是在第一次使用時它只會被計算一次),因此修改上面的代碼以override lazy val foo: Int = 42將導致在打印42。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM