在测试我最近创建的一些代码时,我发现如果没有显式类型注释,某些段落将无法编译。我尝试将以下代码段中的问题最小化:
case class Base[E,S](al:Set[E],sts:Set[MidState[S]],ss:MidState[S],
d:Map[(MidState[S],E),MidState[S]],aS:Set[MidState[S]])
case class Edge[E,S](state_1: MidState[S],l:E ,state_2: MidState[S])
sealed trait MidState[S] extends BaseState[S]
sealed case class State[S](l:S)
extends MidState[S]
case object FailureState extends MidState[Nothing]
Base有一个伴随对象,其apply方法定义如下:
object Base {
def apply [E,S](edges:Set[Edge[E,S]],ss:MidState[S],
aS:Set[MidState[S]],partialMode:Boolean): Base[E,S]
当我尝试使用此apply方法实例化Base时,我无法绕过aS的显式类型注释:
val aS : Set[MidState[String]] = (State("C") :: Nil).toSet
val base = Base(edges,State("A"),aS,partialMode = true)
如果我删除了 aS 的显式类型注释,则 aS 的类型为 Set [State [S]] ,而不是设置[MidState [S]] ,它是应用方法所必需的。尽管将(State(“ C”):: Nil).toSet 直接插入到apply方法中,还有什么更好的解决方案可以避免这种显式类型注释?
答案 0 :(得分:2)
您可以做的第一件事是消除所有:: Nil
和.toSet
和: ...
的噪音:
val aS = Set[MidState[String]](State("C"))
这实际上很常见:例如,它经常作为fold
中的第一个参数出现,其中必须显式编写Set[Int]()
或Set.empty[Int]
以获取类型是的。
如果仍然很嘈杂,只需将适当的工厂方法添加到MidState
:
object MidState {
def apply[S](s: S): MidState[S] = State(s)
}
,然后调用立即构造正确类型的对象的工厂方法:
val bS = Set(MidState("C"))
答案 1 :(得分:0)
Andrey Tyukin引入了一种解决方案,方法是将工厂方法添加到MidState类中,效果很好。但是,我通过在apply-method上添加类型限制来解决了这个问题,因此签名更改为:
object Base {
def apply [E,S](edges:Set[Edge[E,S]],ss:MidState[S],
aS:Set[MidState[S]],partialMode:Boolean): Base[E,S]
收件人:
object Base {
def apply [E,S](edges:Set[Edge[E,S]],ss:MidState[S],
aS:Set[_ <: MidState[S]],partialMode:Boolean): Base[E,S]
现在,我们可以传递任何包含 MidState 子类型的元素的Set aS ,这正是我所要的。