2016-05-31 2 views
1

Я пытаюсь скомпилировать следующий код:Scala - использование параметризованную типа внутри параметризованном типа

case class Settings(settingsList:List[Setting]) 
abstract class Setting[T](name:String, value:T) 

но компилятор жалуется:

Error:(9, 54) class Setting takes type parameters 
case class Settings(settingsList:List[Setting]) 
                ^

но эквивалентный код Java компилируется sucesfully:

public class Settings { 
    List<Setting> settingsList; 
} 

abstract class Setting<T> { 
    abstract T getValue(); 
    abstract String getName(); 
} 

В чем отличие Scala от такого поведения?

ответ

1

Java был создан с версией 5 и AFAIK для обратной совместимости, вы можете опустить параметры типа. Кроме того, Java имеет отклонение от использования сайта, которое обычно делает эти вещи очень неприятными для ввода, в отличие от дисперсии на сайте в Scala. Без изменений вы можете использовать экзистенциальный тип List[Setting[_]] в Scala, но, вероятно, лучше использовать правильную дисперсию:

case class Settings(settingsList: List[Setting[Any]]) 

abstract class Setting[+A](name: String, value: A) 
+0

Мессинг с отклонениями не всегда является лучшей идеей. В зависимости от деталей реализации для настройки ковариация может не иметь смысла и ограничивает дизайн. Подстановочный знак выглядит как путь. –

+0

@UlysseMizrahi Это не «беспорядок». Я рекомендую всегда аннотировать типы с отклонениями, где это имеет смысл. Так работает система, основанная на подтипах, и Scala предпочитает неизменные структуры данных, поэтому это имеет большой смысл. Если это невозможно, как я уже отмечал, вы можете использовать экзистенциальный (групповой) тип. –

+0

«Так работает система, основанная на подтипах» - это просто неверно, и хотя ковариация действительно связана с неизменяемостью, принуждение ковариационных средств неспособно использовать тип в параметрах метода (что может быть желательно даже в неизменяемых структурах). Кроме того, дисперсия имеет фактическое значение с точки зрения типового дизайна. Мы хотим, чтобы параметр [Список [Int]] был настройкой [Итерируемый [Int]]? Это может не иметь смысла с дизайнерской точки зрения. –

3

Вам просто нужен тип подстановочные:

case class Settings(settingsList:List[Setting[_]]) 
abstract class Setting[T](name:String, value:T) 

Это эквивалентно кода Java ,

0

эквивалентный код Java компилируется sucesfully

Setting без параметра типа является исходным типом. По Java documentation,

Использование сырья типов допускается только в качестве уступки совместимости унаследованного кода. Использование необработанных типов в коде, написанном после введения родословности в язык программирования Java, настоятельно не рекомендуется. Возможно, что будущие версии языка программирования Java будут запрещать использование необработанных типов.

Правильный способ написать это в Java является

List<Setting<?>> settingsList; 

и эквивалент Scala является List[Setting[_]], как говорят другие ответы.

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