2016-10-20 8 views
1

В Scala REPL Я могу использовать Seq[String]() в качестве значения по умолчанию для параметра типа Seq[T].IntelliJ IDEA: значения параметров по умолчанию в Scala

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> def d[T](foo: Seq[T] = Seq[String]()) = 12 
d: [T](foo: Seq[T])Int 

scala> d() 
res0: Int = 12 

Попытка же самое в IDEA, он жалуется на «Seq [String] не соответствует ожидаемому типу Seq [T]». Почему?

Screenshot of IDEA complaining about a type problem for parameter default values

  • IntelliJ IDEA 2016.2.4
  • Scala Plugin 2016.2.1
  • Scala 2.11.7

Примечание 1: К сожалению, я знаю, что мой пример функции делает не имеет большого смысла. Однако моя настоящая (и полезная) функция излишне сложна, чтобы опубликовать ее здесь.

Примечание 2: Во-первых, вместо типа T мое имя типа в примере был Любой, который не является хорошей идеей (потому что слежка scala.Any) и вызвало некоторое замешательство. Таким образом, я исправил это.

+0

Я пробовал тот же код в eclipse с той же версией scala. К моему удивлению, я не получаю никаких ошибок – BDR

+1

Как ни странно, если я скопирую вашу часть кода в IntelliJ, у меня будет тот же красный подчеркнутый текст. Но процесс компиляции просто прекрасен. Я предполагаю, что это ошибка в плагине IntelliJ Scala, вот и все. – Polentino

+1

Это действительно ошибка в совместимости с плагином IntelliJ Scala. Я создал проблему: https://youtrack.jetbrains.com/issue/SCL-10892 –

ответ

1

Когда вы говорите def d[Any], Any здесь является общим местом для хранения. Он не указывает на класс Any в scala. Он в основном затеняет класс Any, определенный глобально в scala. Итак, когда вы назначаете Seq[String] в Seq [Any], компилятор не знает никакого отношения между String и Any. Обратите внимание, что Any может быть заменен любым символом/словом в качестве универсального владельца места. Результат будет таким же.

Теперь, почему это работает в REPL, я не совсем уверен, почему REPL принимает, если Seq[String] при задании в качестве значения по умолчанию, но я смог воспроизвести ошибку в repl при выполнении той же операции внутри метода тело.

Следующий код в РЕПЛ бросает ошибку:

def d[Any](foo: Seq[Any]) = { 
    val a: Seq[Any] = Seq[String]() 
} 
<console>:12: error: type mismatch; 
found : Seq[String] 
required: Seq[Any] 
     val a: Seq[Any] = Seq[String]() 
            ^

Я не знаю, почему РЕПЛ не смог поймать ошибку при дается в качестве аргумента по умолчанию.

Одна альтернативная теория заключается в том, что, вообще говоря, при использовании дженериков значение типа будет определяться на основе вызывающего. Например,

def d[A](a:A) = {} 
d(1) // Type of A is Int 
d("a") // Type of A is String 

Итак, когда вы даете значение по умолчанию, он присваивает значение String к Any. следовательно, успех компиляции. TypeTickey Type Checker работает на основе первой теории и показывает ошибку. Но, как ни странно, кто-то указывал ранее, компиляция преуспевает.

+0

@Arvind Но ошибка не происходит в eclipse – BDR

+0

@BalajiReddy Как я уже сказал, это может быть так, как работает Type Checker Intellij Idea.Возможно, Eclipse правильно поняла. Кроме того, поскольку REPL & Scala IDE для eclipse реализованы разработчиками Scala, это, по-видимому, правильный подход. Поэтому это делает вывод о том, что вторая теория, о которой я упомянул, является точным ответом. –

+1

'Seq' является ковариантным. Это означает, что 'Seq [+ A]' может принимать подклассы 'A' в последовательности. Это не означает 'Seq [String]' соответствует 'Seq [T]'. Вы не можете подтвердить это, если 'T' не связано с' String'. Даже «Список» ковариантен. Насколько я понимаю, Intellij покажет ошибку, даже если вы используете 'def d [T] (foo: Seq [T] = Seq [String]()) = {}'. Но будет успешно скомпилироваться. Я думаю, что ответ - ошибка с проверкой типа intellij. Это поможет вам изменить свой вопрос на 'def d [T] (foo: Seq [T] = Seq [String]()) = {}', чтобы избежать путаницы между классом 'Any', определенным в scala и параметром type. –

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