[英]Understanding Pattern Matching with Sub-classes
Lift有Box案例类。
我在Box[A]
上编写了以下方法来模式匹配:
scala> import net.liftweb.common._
import net.liftweb.common._
scala> def foo[A](box: Box[A]) = box match {
| case Empty | Failure(_, _, _) => true
| case Full(_) => false
| }
foo: [A](box: net.liftweb.common.Box[A])Boolean
我写了这个方法来了解ParamFailure
,它是一个Failure
的子类,是否会在Failure(_, _, _)
情况下模式匹配。
scala> val pf: Box[String] = ParamFailure("a", Empty, Empty, "blah")
pf: net.liftweb.common.Box[String] = ParamFailure(a, Empty, Empty, blah)
而且,确实如此。
scala> foo(pf)
res9: Boolean = true
我不清楚ParamFailure
为什么会匹配Failure(_, _, _)
。 这是为什么?
这是继承的全部要点。 如果S
是C
的子类,那么你应该能够在任何使用C
地方绝对使用S
(这称为Liskov替换原则 )。
包括模式匹配。
现在,如果你特别想知道你是否有一个S
而不是一个C
,你可以检查它:
class C {}
class S extends C {}
val c: C = new S
c match {
case s: S => println("Actually, I was an S")
case _ => println("Guess I was some other kind of C")
}
但如果你问它是否是C
,答案是肯定的:
c match {
case c2: C => println("Yes, of course I am a C!")
case _ => println("This would be super-weird.")
}
再次,添加模式匹配在此不做任何改动; 无论您是否知道类型,然后手动提取参数,或者Scala是否有助于为您提供标识符,它的工作方式相同。
case class P(p: Boolean) {}
object T extends P(true) {}
val p: P = T
p match {
case P(tf) => println(tf)
case _ => println("You will never reach here.")
}
这就是规范中定义案例类的方式。
提取器接受case类的实例(即,unapply方法接受C)并返回第一个参数列表的元素。
您可以想象其他定义,例如要求擦除类型完全相同,或者至少productArity
是相同的。
模式匹配被定义为测试形状 ,而不仅仅是或主要作为类型测试或相等测试。
实际上, 构造函数模式的规范并没有直接解决子类型:
该模式匹配从构造函数调用c(v1,...,vn)创建的所有对象
当然,子类构造必然会调用该构造函数。
当一个case类可以扩展另一个case类时 ,可能会有更高的期望,模式匹配会区分子类,但那是在我的时间之前:
$ scala27
Welcome to Scala version 2.7.7.final (OpenJDK 64-Bit Server VM, Java 1.6.0_33).
Type in expressions to have them evaluated.
Type :help for more information.
scala> case class A(i: Int)
defined class A
scala> case class B(j: Int, s: String) extends A(j)
defined class B
scala> (B(7,"hi"): Any) match { case A(7) => 1 case B(_,_) => 2 }
res1: Int = 1
scala> B(7,"hi").productArity
res2: Int = 2
我从文法学校知道,有些骆驼有一个驼峰,有些有两个。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.