简体   繁体   English

如何在Scala中的函数签名中匹配类型成员?

[英]How to match on type member in function signature in Scala?

For obscure reasons due to a specific library I'm using involving macros and serialization, I have chosen to try to use type members instead of type parameters for a class (background: Is there a way to use ClassTags with the Autowire library in Scala? ) 出于晦涩的原因,由于我正在使用涉及宏和序列化的特定库,我选择尝试为类使用类型成员而不是类型参数(背景: 是否可以在Scala中将ClassTag与Autowire库一起使用?

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){
  //...
}

Is there a way to do this statically? 有没有办法静态地做到这一点? I think using type classes and context bounds is one option, but I feel it is a bit heavy handed since I'm already using subclassing here. 我认为使用类型类和上下文边界是一种选择,但是我觉得这有点麻烦,因为我已经在这里使用子类化了。 Perhaps the better option is just to make metadata a trait, and embrace object oriented more fully and create all kinds of variations of Command based on which traits are mixed in. 也许更好的选择只是使元数据成为特征,并更加全面地面向对象,并基于混合了特征的方式创建Command的各种变体。

You can define the function argument with a refined type: 您可以使用精炼类型定义函数参数:

def runInSystem(cmd: Command { type M <: SysCmdMetaData }) = { }

Note that unlike type parameters, type members are not inferred by default . 请注意,与类型参数不同,默认情况下不会推断类型成员 The following code will fail: 以下代码将失败:

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)
                   ^

You'd have to either: 您必须:

  • Use some named subclass of Command , where M is statically fixed to an appropriate type. 使用Command某些命名子类,其中M静态固定为适当的类型。
  • Pass an anonymous subclass instance directly to runInSystem : 将匿名子类实例直接传递给runInSystem

     runInSystem(new Command { type M = SysCmdMetaData val meta = SysCmdMetaData() }) 
  • Manually prescribe the type member of the variable you pass to runInSystem : 手动规定传递给runInSystem的变量的类型成员:

     val cmd: Command { type M = SysCmdMetaData } = new Command { type M = SysCmdMetaData val meta = SysCmdMetaData() } runInSystem(cmd) 
  • You can also define a type alias with a type parameter: 您还可以使用类型参数定义类型别名:

     object Command { type Aux[M0 <: CommandMetaData] = Command { type M = M0 } } val cmd: Command.Aux[SysCmdMetaData] = ??? runInSystem(cmd) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM