首页 文章

在所有情况下都不强制键入别名参数边界

提问于
浏览
12

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 回答

  • 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

相关问题