TL; DR: Похоже, что параметры типа псевдонимов типов (например, type T[X<:Serializable]
) не применяют их ограничения, если они упоминаются как переменные, параметры и, возможно, другие случаи. Тем не менее, классы классов правильно применяют границы для своих параметров.
Рассмотрим псевдоним типа, предназначенный для представления подмножества родового типа. Например, скажем, я хочу тип для списков Serializable
вещей:
scala> type SerializableList[T <: Serializable] = List[T]
defined type alias SerializableList
Теперь скажите, что я хочу класс case с параметром этих вещей:
scala> case class NetworkDataCC(things: SerializableList[_])
<console>:9: error: type arguments [_$1] do not conform to type SerializableList type parameter bounds [T <: Serializable]
case class NetworkDataCC(things: SerializableList[_])
Ну, это не работает. Scala (досадно) не несет оценки параметров с типом, но легко исправить:
scala> case class NetworkDataCC(things: SerializableList[_ <: Serializable])
defined class NetworkDataCC
Хорошо. Выглядит неплохо. Теперь, если я хочу только обычный класс с этими вещами, но я снова забываю явно объявлять границы типов. Я ожидаю ошибку:
scala> class NetworkData(val things: SerializableList[_])
defined class NetworkData
Ой, подождите. Нет ошибки... да.
Итак, теперь я могу это сделать?
scala> new NetworkData(List(1))
res3: NetworkData = [email protected]
Хорошо, это кажется очень сломанным. Класс case, конечно, отлично работает (поскольку были объявлены ограничения):
scala> NetworkDataCC(List(1))
<console>:11: error: type mismatch;
found : Int(1)
required: Serializable
NetworkDataCC(List(1))
В моем проекте я использую отражение для генерации некоторых метаданных о моих классах. Метаданные для не-case-класса показывают отсутствие границ на things
:
scala> classOf[NetworkData].getDeclaredFields()(0).getGenericType
res0: java.lang.reflect.Type = scala.collection.immutable.List<?>
В то время как класс case правильный:
scala> classOf[NetworkDataCC].getDeclaredFields()(0).getGenericType
res1: java.lang.reflect.Type = scala.collection.immutable.List<? extends scala.Serializable>
Я не смог найти ошибок в Scala компиляторе для отслеживания ошибок. Я не понимаю, как эти границы следует использовать?