由于我正在使用涉及宏和序列化的特定库,由于模糊的原因,我选择尝试使用类型成员而不是类的类型参数(background:Is there a way to use ClassTags with the Autowire library in Scala?)
sealed trait Command {
type M <: CommandMetaData
val meta: M
}
final case class SysCmdMetaData(
// ...
) extends CommandMetaData
// How to guarantee cmd.M <: SysCmdMetaData
def runInSystem(cmd: Command){
//...
}
有没有办法静态地这样做?我认为使用类型类和上下文边界是一种选择,但我觉得它有点沉重,因为我已经在这里使用子类。也许更好的选择只是使元数据成为特征,并更充分地拥抱面向对象,并根据混合的特征创建Command的各种变体。
您可以使用精炼类型定义函数参数:
def runInSystem(cmd: Command { type M <: SysCmdMetaData }) = { }
请注意,与类型参数不同,type members are not inferred by default。以下代码将失败:
scala> val cmd: Command = new Command {
type M = SysCmdMetaData
val meta = SysCmdMetaData()
}
cmd: Command = $anon$1@830b8a5
scala> runInSystem(cmd)
<console>:15: error: type mismatch;
found : cmd.type (with underlying type Command)
required: Command{type M <: SysCmdMetaData}
runInSystem(cmd)
^
你必须要么:
Command
的一些命名子类,其中M
被静态固定为适当的类型。runInSystem
:
runInSystem(new Command {
type M = SysCmdMetaData
val meta = SysCmdMetaData()
})
runInSystem
的变量的类型成员:
val cmd: Command { type M = SysCmdMetaData } = new Command {
type M = SysCmdMetaData
val meta = SysCmdMetaData()
}
runInSystem(cmd)
object Command {
type Aux[M0 <: CommandMetaData] = Command { type M = M0 }
}
val cmd: Command.Aux[SysCmdMetaData] = ???
runInSystem(cmd)