在Scala中合并多个case(在match/case中)

pro*_*eek 1 controls scala

我有instance.get返回值的代码,并根据类型I进行相应处理.

  instance.get match {
    case v:Range  => {
      val sizeInBytes = util.conversion.Util.getBytesForBits(v.size)
      val value = v.decode(contentByteArray.slice(index, index + sizeInBytes))
      index += sizeInBytes
      res(key) = value
    }
    case v:Encoding => {
      val sizeInBytes = util.conversion.Util.getBytesForBits(v.size)
      val value = v.decode(contentByteArray.slice(index, index + sizeInBytes))
      index += sizeInBytes
      res(key) = value
    }
    ...
  }
Run Code Online (Sandbox Code Playgroud)

在代码中,我有RangeEncoding类型的重复.我如何合并这两个案例?

我尝试了|操作员,但它不起作用.

case v:Range | v:Encoding
Run Code Online (Sandbox Code Playgroud)

Dim*_*ima 5

这可不行,因为Range.sizeEncoding.size是尽管它们被命名为相同的两个完全不同的方法.同样适用于Range.decodeEdncoding.decode.

所以,当你写作时v.size,v必须知道它的类型,它必须是v:Encoding或者v:Range不是v:Encoding|v:Range.

如何解决这个问题?做一个像这样的共同特征:

 trait SomethingWithDecodeAndSize {
   def size: Int
   def decode(bytes: Array[Byte]): Whatever
 }
Run Code Online (Sandbox Code Playgroud)

然后,改变的定义RangeEncoding:

class Range extends SomethingWithDecodeAndSize { ... }
class Encoding extends SomethingWithDecodeAndSize { ... }
Run Code Online (Sandbox Code Playgroud)

现在你可以case v: SomethingWithDecodeAndSize => ...在你的匹配条款中做.

还有......不要这样做instance.get,那味道不好.相反

instance match { 
   Some(v: SomethingWithDecodeAndSize) => ...
}
Run Code Online (Sandbox Code Playgroud)

更新 如果无法修改原始类的定义,则可以使用提取器:

object SomethingWithDecodeAndSize {
   def unapply(a: Any): Option[SomethingWithDecodeAndSize] = a match {
      case r: Range => Some(new SomethingWithDecodeAndSize {
        def size = r.size
        def decode(bytes: Array[Byte]) = r.decode(bytes)
      })
      case r: Encoding => Some(new SomethingWithDecodeAndSize {
        def size = r.size
        def decode(bytes: Array[Byte]) = r.decode(bytes)
      })
      case _ => None
   }
 }
Run Code Online (Sandbox Code Playgroud)

现在,你可以case Some(SomethingWithDecodeAndSize(v)) => ...在你的比赛中做到.