TL; DR:似乎类型别名的类型参数(例如type T[X<:Serializable]
)在引用为变量,参数和其他情况时不会强制执行它们的约束。但是,案例类会对其参数正确执行边界。
考虑用于表示泛型类型子集的类型别名。例如,让我们说我想要Serializable
事物列表的类型:
scala> type SerializableList[T <: Serializable] = List[T]
defined type alias SerializableList
现在说我想要一个带有这些参数的案例类:
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编译器错误跟踪器中找到任何错误。我是否误解了应该如何使用这些界限?
答案 0 :(得分:4)
默认情况下,Scala的下划线不等同于SerializableList[X forSome {type X}]
:
scala> def aa(a: SerializableList[_]) = a
aa: (a: SerializableList[_])List[Any]
scala> def aa(a: SerializableList[X forSome {type X}]) = a
<console>:11: error: type arguments [X forSome { type X }] do not conform to type SerializableList's type parameter bounds [T <: Serializable]
def aa(a: SerializableList[X forSome {type X}]) = a
^
scala> class NetworkDataCC(things: SerializableList[X forSome {type X}])
<console>:11: error: type arguments [X forSome { type X }] do not conform to typ
e SerializableList's type parameter bounds [T <: Serializable]
class NetworkDataCC(things: SerializableList[X forSome {type X}])
相当于
scala> def aa(a: SerializableList[X] forSome {type X} ) = a
aa: (a: SerializableList[_])List[Any]
所以这种“无限制”的行为很好。看看这个答案:https://stackoverflow.com/a/15204140/1809978
案例类似乎有其他类型限制(由this bug引起,影响unapply
方法,为案例类自动生成。)
如果你想在case类中使用“unbounded”存在类型,只需明确指定高阶类型:
scala> case class NetworkDataCC[SerializableList[_]](things: SerializableList[_])
warning: there were 2 feature warning(s); re-run with -feature for details
defined class NetworkDataCC
scala> NetworkDataCC(List(1))
res5: NetworkDataCC[List] = NetworkDataCC(List(1))
甚至:
scala> type SLL = SerializableList[_]
defined type alias SLL
scala> case class NetworkDataDD(things: SLL)
defined class NetworkDataDD
所以这绝对是一个错误,您可以使用语义上等效的类型别名来解决它(请参阅SI-8997)