スタックオーバーフローには、 Scalaで末尾再帰が可能な条件を説明するさまざまな回答があります。制限と、末尾再帰を利用する方法と場所を理解しています。私が理解していない部分は、プライベートメソッドまたはfinalメソッドへの制限が存在する理由です。
Scalaコンパイラが実際に再帰関数をバイトコードレベルで非再帰関数に変換する方法については調査していませんが、次のような動作をすると仮定します。Foo
再帰関数を持つクラスがありますmod
:
class Foo {
def mod(value: Int, denom: Int): Int = {
if(denom <= 0 || value <= 0) 0
else if(0 <= value && value < denom) value
else mod(value - denom, denom)
}
}
これは基本的なモジュロ関数であり、Scalaコンパイラーが次のような疑似Java-Scalaに変換されると思います。
class Foo {
def mod(value: Int, denom: Int): Int = {
if(denom <= 0 || value <= 0) return 0
while(value > denom) value -= denom
return value
}
}
(私はその翻訳を台無しにしたと信じることができますが、詳細は重要ではないと思います。)
だから今私がサブクラスだとしましょうFoo
:
class Bar extends Foo {
def mod(value:Int, denom: Int): Int = 1
}
これが機能しなくなるのは何ですか?JVMにとが呼び出されたときFoo/Bar
に、使用する必要mod
のある関数の解決に問題があるのはなぜですか。mod
これは、基本関数が非再帰的である状況と異なるのはなぜですか?
これが事実であると私が見ることができるいくつかの考えられる理由は次のとおりです。
何らかの理由で、Scalaコンパイラーの実装はこれを処理しません(その場合は十分に公平です。もしそうなら、これを変更する計画はありますか?)
関数内
Foo
はコンパイル中に変更されるため、実際にはオーバーライドするメソッドはありません。mod
mod-non-recursive
Foo
mod