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's 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 = NetworkData@e344ad3
嗯,这似乎很破碎 . 案例类,当然可以正常工作(因为声明了限制):
scala> NetworkDataCC(List(1))
<console>:11: error: type mismatch;
found : Int(1)
required: Serializable
NetworkDataCC(List(1))
在我的项目中,我正在利用反射来生成关于我的类的一些元数据 . 非案例类的元数据显示 things
缺少界限:
scala> classOf[NetworkData].getDeclaredFields()(0).getGenericType
res0: java.lang.reflect.Type = scala.collection.immutable.List<?>
案例类是正确的:
scala> classOf[NetworkDataCC].getDeclaredFields()(0).getGenericType
res1: java.lang.reflect.Type = scala.collection.immutable.List<? extends scala.Serializable>
我无法在scala编译器bug跟踪器中找到任何错误 . 我是否误解了应该如何使用这些界限?
1 回答
默认情况下,Scala的下划线不等同于
SerializableList[X forSome {type X}]
:它相当于
所以这样的行为很好 . 看看这个答案:https://stackoverflow.com/a/15204140/1809978
案例类似乎有其他类型限制(由于this bug,它影响
unapply
方法,为案例类自动生成) .如果你想在case类中使用“unbounded”存在类型,只需明确指定高阶类型:
甚至:
所以这肯定是一个错误,您可以使用语义上等效的类型别名来解决它(请参阅SI-8997)