【问题标题】:Pattern matching over non-case class in ScalaScala中非案例类的模式匹配
【发布时间】:2013-11-17 14:41:01
【问题描述】:

假设我有一个普通的第三方(即我不能修改它)类定义如下:

class Price(var value: Int)

这是否可以将此类的实例与某些模式匹配?

比如我要实现函数:

def printPrice(price: Price) = {
    // implementation here
}

...在所有其他情况下,为每个具有value <= 9000price is over 9000price 打印price is {some value}

例如调用:

printPrice(new Price(10))
printPrice(new Price(9001))

应该打印:

price is 10
price is over 9000

如何使用模式匹配实现printPrice

【问题讨论】:

  • (1) 确定Pricevalue 的公共访问器?因为如果value 是私有的,你就无法提取它。 (2) 如果是class Price(val value: Int),为什么不直接println(s"price is ${price.value}")
  • @0__ 感谢您指出 (1)。解决了我的问题。

标签: scala pattern-matching


【解决方案1】:

您可以创建自定义提取器:

package external {
    class Price(var value: Int)
}

object Price {
    def unapply(price: Price): Option[Int] = Some(price.value)
}

def printPrice(price: Price) = price match {
    case Price(v) if v <= 9000 => println(s"price is $v")
    case _ => println("price is over 9000")
}

printPrice(new Price(10))
printPrice(new Price(9001))

对于案例类,编译器会自动生成它。我认为在你的情况下提取器是矫枉过正的,但可能只是简化的样本。

【讨论】:

  • 您只能在定义类的同一文件中为某些类定义伴随对象。考虑到这一点,您的解决方案似乎不适用于我的场景(类来自第三方库)。
  • Extractor 不限于作为伴生对象。你可以在任何地方定义它。我更新了我的答案。
【解决方案2】:

考虑过接受弗拉维安的解决方案,但我自己想出了更好的解决方案。

以下是如何实现printPrice(无需使用包装对象和修改原始类):

def printPrice(price: Price) = price match {
    case p: Price if (p.value <= 9000) => println("price is " + p.value)
    case p: Price => println("price is over 9000")
}

PS:感谢 flavian 证明您可以在模式中使用 if。对此表示赞同。

【讨论】:

【解决方案3】:

您可以使用 PIMP 我的库模式:

case class RichPrice(value: Int) {}
  implicit def priceToRichPrice(price: Price): RichPrice = RichPrice(price.value)

  def printPrice(x: RichPrice): Unit = {
    x match {
      case RichPrice(value) if (value <= 9000) => println("below 9000")
      case RichPrice(value) if (value > 9000) => println("over 9000")
      case _ => println("wtf")
    }
  }
println(printPrice(new Price(10)))
println(printPrice(new Price(9001)))

使用case class 的目的是让Scala 定义apply 方法和unapply 用于模式匹配的魔法。

【讨论】:

  • 先生。投票者来了!我认为您在自定义编写的 unapply 将是一个更清洁的解决方案的地方滥用了具有不必要代理的隐式转换。 EDIT 错过了第三方的东西 :-(
  • @flavian by case def applycase def unnaply 你的意思是 apply / unapply 案例类 (RichPrice) 上的方法吗?
猜你喜欢
  • 2017-02-25
  • 1970-01-01
  • 2017-04-25
  • 2014-08-12
  • 1970-01-01
  • 2013-09-13
  • 1970-01-01
  • 2016-08-13
  • 1970-01-01
相关资源
最近更新 更多