2013-09-18 3 views
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 

Если степени свободы: Int = 0 изменяются на степеней свободы: Int, тем пример компилируется и работает как ожидалось.

Кажется уродливым, что наличие или отсутствие значения параметра по умолчанию изменяет, является ли код действительным или нет.

Какое объяснение, почему это действительно имеет смысл?

+0

Первый имеет смысл, так как при перегрузке метода Scala только путем проверки первого аргумента и из-за стирания стилей он одинаковый, следовательно, и ошибка. Выполнение 'dof: Int' очень странно. Я не вижу никаких аргументов в руководстве – Jatin

ответ

5

Проблема заключается в том, что при использовании аргументов по умолчанию его имя и имя метода используются для генерации статического атрибута, таким образом: [methodName]$default$[argumentPosition], в вашем случае это будет variance$default$2, поэтому, если оба имеют аргументы по умолчанию, компилятор попытается создать 2 статических атрибута с тем же именем.

Если тип других аргументов в методе был использован, этого можно было бы избежать. Вы можете submit a SIP Предложение об изменении этого поведения в компиляторе.

Вы можете прочитать об этом на этом post

Если вы хотите проверить самостоятельно, попробуйте скомпилировать ваш объект с каждым методом и осмотрите класс, используя 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); 
} 

и ваш второй метод даст:

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); 
} 

наконец, пути удаления значения по умолчанию для степеней свободы во втором методе, мы получаем:

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() - это то, что делает компиляцию неудачной, которая генерируется значением по умолчанию.

Смежные вопросы