我想使用Scala提取器将我的自定义类型与String
匹配(按特定顺序,而不是String
到Scala
)。这是我的代码:
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
方法,以便进行提取。
答案 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
中提取点数。在这种情况下,ValueBeingMatched
为String
,ExtractedValue
为Point
。我还将在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!")
}