1. ホーム
  2. scala

[解決済み] Scala コンパイラは、なぜデフォルトの引数を持つオーバーロードされたメソッドを許可しないのですか?

2022-05-06 01:44:21

質問

このようなメソッドのオーバーロードが曖昧になる正当なケースもあるかもしれませんが、コンパイル時や実行時に曖昧でないコードをコンパイラが許可しないのはなぜですか?

// This fails:
def foo(a: String)(b: Int = 42) = a + b
def foo(a: Int)   (b: Int = 42) = a + b

// This fails, too. Even if there is no position in the argument list,
// where the types are the same.
def foo(a: Int)   (b: Int = 42) = a + b
def foo(a: String)(b: String = "Foo") = a + b

// This is OK:
def foo(a: String)(b: Int) = a + b
def foo(a: Int)   (b: Int = 42) = a + b    

// Even this is OK.
def foo(a: Int)(b: Int) = a + b
def foo(a: Int)(b: String = "Foo") = a + b

val bar = foo(42)_ // This complains obviously ...

この制限をもう少し緩めることはできないのでしょうか?

特に、オーバーロードの激しいJavaコードをScalaに変換する場合、デフォルトの引数は非常に重要で、たくさんのJavaメソッドを1つのScalaメソッドに置き換えた後に、仕様やコンパイラが任意の制限を課していることに気づくのは良いことではないでしょう。

どうすればいい?

Lukas Rytzを引用したいと思います(from こちら ):

の決定論的な名前付けスキームが欲しかったからです。 はデフォルトの引数を返すメソッドを生成します。もし

def f(a: Int = 1)

コンパイラが生成する

def f$default$1 = 1

同じパラメータにデフォルトで2つのオーバーロードがある場合 の位置にある場合、異なる命名規則が必要になります。しかし、私たちは は、複数のコンパイラが実行されても、生成されるバイトコードは安定しています。

将来のScalaバージョンでの解決策としては 型名 を名前付けのスキーマに組み込んでいます。

def foo(a: String)(b: Int = 42) = a + b
def foo(a: Int)   (b: Int = 42) = a + b

のようなものでしょう。

def foo$String$default$2 = 42
def foo$Int$default$2 = 42

喜んでくれる人 SIPプロポーザルを作成する ?