5

以下はコンパイルされません。

package play

object Stats2 {
  def variance(data: Seq[Double], dof: Int = 0): Double = {
    println("variance Double direct"); 1.0
  }
  def variance[T](data:Seq[T], dof: Int = 0)(implicit ex: T => Double): Double = {
    println("variance Double extracted"); 1.0
  }
} 

コンパイラは次のように述べています。

$ scalac erasure2.scala 
erasure2.scala:7: error: double definition:
method variance$default$2:[T]=> Int and
method variance$default$2:=> Int at line 4
have same type after erasure: ()Int
  def variance[T](data:Seq[T], dof: Int = 0)(implicit ex: T => Double): Double = {
                               ^
one error found

dof :Int = 0をdof: Intに変更すると、サンプルはコンパイルされ、期待どおりに動作します。

コードが有効か無効かでパラメータのデフォルト値の有無が変わるのは醜い。

これが本当に理にかなっている理由の説明は何ですか?

4

1 に答える 1

5

問題は、デフォルト引数を使用する場合、その名前とメソッド名が次のように静的属性を生成するために使用される[methodName]$default$[argumentPosition]ことvariance$default$2です。同じ名前の属性。

メソッド内の他の引数の型が使用された場合、これは回避できます。コンパイラでこの動作を変更するには、SIP 提案を提出することができます。

詳細については、この投稿をご覧ください。

自分で確認したい場合は、各メソッドでオブジェクトをコンパイルし、 を使用してクラスを検査してみてくださいjavap [XXX]。ここで、 はオブジェクトまたはクラスの名前ですjavap Stats2
最初の方法は次のようになります。

public final class Stats2 extends java.lang.Object{
    public static final int variance$default$2();
    public static final double variance(scala.collection.Seq, int);
}

2番目の方法では次のようになります。

public final class Stats2 extends java.lang.Object{
    public static final int variance$default$2();
    public static final double variance(scala.collection.Seq, int, scala.Function1);
}

最後に、2 番目のメソッドで dof のデフォルト値を削除すると、次のようになります。

public final class Stats2 extends java.lang.Object{
    public static final double variance(scala.collection.Seq, int, scala.Function1);
}

そのためstatic final int variance$default$2()、デフォルト値によって生成されるコンパイルが失敗する原因となっています。

于 2013-09-18T18:04:58.073 に答える