如何扩展String以添加新的unapply函数以便在提取时使用它?

时间:2015-10-19 22:49:49

标签: scala

我想使用Scala提取器将我的自定义类型与String匹配(按特定顺序,而不是StringScala)。这是我的代码:

class Scala

object Scala {
  def apply(s: String) = new Scala
  def unapply(sc: Scala) = Some("Scala")
}

class ExtendedString(s: String) {
  def unapply(sc: Scala): Option[String] = {
    Some(s)
  }
}

implicit def str2Scala(s: String): ExtendedString = {
  new ExtendedString(s)
}

Scala match {
  case "abc" => println("Aha!")
  case "def" => println("Yeah!")
  case "scala" => println("Scala!")
}

但它不起作用。我收到一个错误:

Error:(20, 9) type mismatch;
 found   : String("abc")
 required: A$A109.this.Scala.type
  case "abc" => println("Aha!")
       ^

如何修复它以使提取器工作?

PS

我最初的想法是提供一个隐式转换器,用String类扩展ExtendedString类,然后在那里实现unapply方法,以便进行提取。

1 个答案:

答案 0 :(得分:2)

如果你想要的只是一个提取器,那么就不需要任何暗示。

要定义提取器,请使用object方法生成unapply。 E.g。

object MyExtractor {
  def unapply(value: ValueBeingMatched): Option[ExtractedValue] = { ... }
}

然后使用提取器匹配值

val myValue: ValueBeingMatched = ...
myValue match {
  case MyExtractor(extractedValue) => println(s"I got $extractedValue!")
}

如果您希望提取器返回多个值,则unapply应返回元组选项:

object MyExtractor {
  def unapply(value: ValueBeingMatched): Option[(ResultType1, ResultType2, ...)] = { ... }
}

val myValue: ValueBeingMatched = ...
myValue match {
  case MyExtractor(result1, result2, ...) => ...
}

我不清楚你要从你的示例代码中完成什么,所以我会做一个可能与你相关的例子。

我们假设您制作了自定义Point课程:

case class Point(x: Int, y: Int)

并且您希望能够从String中提取点数。在这种情况下,ValueBeingMatchedStringExtractedValuePoint。我还将在Point对象中定义提取器。至于功能,我们假设像"12,8"这样的字符串对应于Point(12, 8)

object Point {
  def unapply(s: String): Option[Point] = {
    val parts = s.split(",")
    // this is just example code, so I won't handle failures,
    // but if it did fail, you'd return a None instead of Some
    Some(Point(parts(0).toInt, parts(1).toInt))
  }
}

现在已定义,您可以使用Point提取器匹配字符串:

val s = "3,4"
s match {
  case Point(p) => // p is actually an instance of Point
}

编辑以回复反馈:

为了直接匹配字符串,匹配的值必须已经 一个字符串。因此,一种方法是添加转换器方法,例如

instanceOfMyType.convertToString match {
  case "abc" => println("Aha!")
}

或者您必须编写一个允许

的提取器
instanceOfMyType match {
  case Extracted("abc") => println("Aha!")
}