如何在 Scala 中使用不带大小写 类 的模式匹配?
how to use pattern matching without case classes in scala?
我听说我们可以在 Scala 中应用模式匹配而无需使用 case classes。另外,我的意思不是仅仅识别实际实现 class,而是从对象中提取各种值。真的可能吗?我们怎样才能做到这一点?
在之前发布的类似主题的任何问题中,我都找不到指向我的解决方案的公认答案。因此,我决定提出一个新问题。
案例 classes 并不神奇,它们在幕后所做的是生成大量样板代码。
在这两者之间,是 apply
(factory constructor) 和 unapply
(extractor) 方法class.
当您尝试 模式匹配 一个对象时,编译器尝试做的是调用伴生对象的 提取器方法 - 因此,您只需要实现您自己的提取器对象。
例如
class User(val id: Int, val name: String)
object User {
def apply(id: Int, name: String): User = new User(id, name)
def unapply(user: User): Option[(Int, String)] =
Some(user.id, user.name)
}
现在您可以通过这种方式创建匹配的用户。
val user = User(3, "Luis")
def getId(user: User): Int = user match {
case User(id, name) => id
}
getId(user) // 3
参考 this。
结合 Arnon 和 Luis 解决方案进行演示:
class A(val a: Int, val b: String, val c: Int)
// Handmade companion object for demonstration purpose only.
object A {
def unapply(u: A): Option[(Int, String, Int)] =
Some(u.a, u.b, u.c)
}
// No factory method found, so 'new' keyword is necessary.
val a = new A(1, "hello", 3)
/* With real case class the right side expression
calls the unapply of the Object
otherwise call must be explicitly.
*/
val Some((b, _, c)) = A.unapply(a)
// b: Int = 1
// c: Int = 3
def getId(user: A): Int = user match {
case A(_, _, id) => id
}
getId(a) // 3
我听说我们可以在 Scala 中应用模式匹配而无需使用 case classes。另外,我的意思不是仅仅识别实际实现 class,而是从对象中提取各种值。真的可能吗?我们怎样才能做到这一点?
在之前发布的类似主题的任何问题中,我都找不到指向我的解决方案的公认答案。因此,我决定提出一个新问题。
案例 classes 并不神奇,它们在幕后所做的是生成大量样板代码。
在这两者之间,是 apply
(factory constructor) 和 unapply
(extractor) 方法class.
当您尝试 模式匹配 一个对象时,编译器尝试做的是调用伴生对象的 提取器方法 - 因此,您只需要实现您自己的提取器对象。
例如
class User(val id: Int, val name: String)
object User {
def apply(id: Int, name: String): User = new User(id, name)
def unapply(user: User): Option[(Int, String)] =
Some(user.id, user.name)
}
现在您可以通过这种方式创建匹配的用户。
val user = User(3, "Luis")
def getId(user: User): Int = user match {
case User(id, name) => id
}
getId(user) // 3
参考 this。
结合 Arnon 和 Luis 解决方案进行演示:
class A(val a: Int, val b: String, val c: Int)
// Handmade companion object for demonstration purpose only.
object A {
def unapply(u: A): Option[(Int, String, Int)] =
Some(u.a, u.b, u.c)
}
// No factory method found, so 'new' keyword is necessary.
val a = new A(1, "hello", 3)
/* With real case class the right side expression
calls the unapply of the Object
otherwise call must be explicitly.
*/
val Some((b, _, c)) = A.unapply(a)
// b: Int = 1
// c: Int = 3
def getId(user: A): Int = user match {
case A(_, _, id) => id
}
getId(a) // 3