枚举和模式匹配

时间:2017-05-19 10:04:29

标签: scala

定义了两个枚举如下。

object DimensionList1 extends Enumeration {
  type DimensionList1 = Value
  val Platform, Region, Service = Value

}

object DimensionList2 extends Enumeration {
  type DimensionList2 = Value
  val Platform, Region, Service, Scope = Value

}

尝试根据输入枚举进行模式匹配。看起来,只要我在初始维度匹配中添加多个case语句,我就不能在第二个匹配语句中使用“dimension.Platform”。编译器抱怨“dimension.Platform - Symbol无法找到”,即使它存在于两个枚举中。

def processFilters(supportedDimension: Enumeration, filters: List[FilterModel])= {
  val dimension = supportedDimension match {
      case DimensionList1 => DimensionList1
      case DimensionList2 => DimensionList2
      case _ => DimensionList1
  }

  // filters is a list of model [dimensionName, dimensionValues]

  for(filter <- filters) yield {
     util.Try(dimension.withName(filter.dimensionName)) match {

          case util.Success(dimension.Platform) => { ** This is not possible **
             // do something 
          }
     }
  }
}

3 个答案:

答案 0 :(得分:1)

您可以创建一个Map,为您的不同枚举值定义处理程序:

def processFilters(supportedDimension: Enumeration, filters: List[FilterModel])= {
    val dimension = supportedDimension
    for(filter <- filters) yield {
      Try(dimension.withName(filter.dimensionName)) match {
        case suc@Success(x) => {
          val handlerFunction = handlers.getOrElse(suc.get, () => {/* we have no handler defined in our handlers Map */})
          handlerFunction() // call the handler function
        }
      }
    }
  }

然后通过以下方式调整processFilters中的代码:

po view.layer.frame.size.height

希望这有帮助!

答案 1 :(得分:0)

您的代码不起作用,因为:

  val dimension = supportedDimension match {
      case DimensionList1 => DimensionList1
      case DimensionList2 => DimensionList2
      case _ => DimensionList1
  }

在上面的代码中,您返回的是不同的类型,即DimensionList1DimensionList2因此,scala会将dimension的类型分配给Enumeration。因此,您无法访问枚举值,例如:dimension.Platform因为Enumeration是一个抽象类没有您的值:平台,区域,服务等。

因此,您需要首先将维度转换为适当的枚举,以便访问其值:

  dimension.isInstanceOf[DimensionList1.type] match {
    case true => {
      val dimen = dimension.asInstanceOf[DimensionList1.type]
      dimen.Platform  //now you have access to enumvalues...
      //code for your filter
    }
    case false => {
      dimension.isInstanceOf[DimensionList2.type] match {
        case true => {
          val dimen = dimension.asInstanceOf[DimensionList2.type]
          dimen.Platform  //now you have access to enum values...
          //code for your filter
        }
        case false =>
          //do something...
      }
    }
  }

      //Another approach.
      dimension match {
        case x: DimensionList1.type => {
          x.Platform //now you have access to enumvalues...
          //code for your filter
        }
        case x: DimensionList2.type => {
          x.Scope //now you have access to enumvalues...
          //code for your filter      
        }
        case //match for more cases.
      }

答案 2 :(得分:0)

这也不是一个好主意,但是:

scala> trait Dimensions { _: Enumeration =>
     |   val Platform, Region, Service = Value
     | }
defined trait Dimensions

scala> object Dim1 extends Enumeration with Dimensions
defined object Dim1

scala> object Dim2 extends Enumeration with Dimensions { val Scope = Value }
defined object Dim2

scala> def f(dims: Enumeration with Dimensions, name: String) = dims.withName(name) match {
     |   case dims.Platform => "platform"
     |   case Dim2.Scope    => "scope"
     | }
<console>:15: error: type mismatch;
 found   : Dim2.Value
 required: dims.Value
         case Dim2.Scope    => "scope"
                   ^

scala> def f(dims: Enumeration with Dimensions, name: String) = (dims.withName(name): Any) match {
     |   case dims.Platform => "platform"
     |   case Dim2.Scope    => "scope"
     | }
f: (dims: Enumeration with Dimensions, name: String)String

scala> f(Dim1, "Region")
scala.MatchError: Region (of class scala.Enumeration$Val)
  at .f(<console>:15)
  ... 29 elided

scala> f(Dim1, "Platform")
res1: String = platform

scala> f(Dim1, "Scope")
java.util.NoSuchElementException: No value found for 'Scope'
  at scala.Enumeration.$anonfun$withName$2(Enumeration.scala:125)
  at scala.Enumeration.withName(Enumeration.scala:125)
  at .f(<console>:13)
  ... 29 elided

scala> f(Dim2, "Scope")
res3: String = scope

类型不匹配说不要这样做;向Any的向上转换不是一种解决方法,而是说“我不再关心了。”