scala中的模式匹配类似与java中的switch语法,但功能比switch更加强大,且能匹配的方式各种各样。
我总结了一下,scala的match的匹配方式有如下几种:
通配模式 常量模式 变量模式 构造器模式 序列模式 元组模式 类型模式在介绍模式匹配之前,先要介绍一下Scala的样本类,样本类可以在模式匹配中使用,而一般的普通类则不行。
先来一个样本类的例子:
abstract class Animal case class Dog() extends Animal case class Person(name: String, age: Int) extends AnimalScala对样本类添加了一些辅助方法: 1、工厂方法
var p = new Dog() var p = Dog()这两句的作用是一样的。 2、样本类的参数被当成字段进行处理
var p = Person("shadon", 28) p.name p.age3、默认实现了toString, hashCode和equals方法
由于以上的三点,因此在使用样本类时非常便利。
匹配person对象,如果是2个参数的则匹配第一个,这个其实是构造器模式,后面会讲到。通配模式的重点在‘_’,表示匹配任意对象。当然通配符‘_’也可以放在类的参数上,用于匹配参数个数,例如:
p match { case Person(_, _) => println("person") case _ => println("other") }常量模式用于匹配常量值,这个好理解。
scala认定变量模式的方式比较奇特:用小写字母开头的变量;
def match1(p: Any): String = { val pp = Math.PI p match { case pp => "PI" } }这里不论传入什么参数,都会被匹配,而且case里面只能使用一个,不然会抛错。如果想将变量模式转变成常量模式只需要增加转义符:`pp`。 思考:这个变量模式我一直想不通,到底有何用途,哪位网友知道请相告知,谢谢!
这里匹配第一个参数为“shadon”的Person。
序列模式主要用于匹配像List, Array这样的序列类。使用‘_*’可以匹配零到多个参数。
def match1(p: Any): String = { p match { case List(9, _, _*) => "9 start" case _ => "no" } }注意在类型模式中使用泛型存在类型擦除的问题:
def match1(p: Any): String = { p match { case map: Map[Int, String] => "Map[Int, String]" case _ => "no" } } def main(args: Array[String]): Unit = { println(match1(Map(1 -> 1, 2 -> 1))) }这里虽然指定了Map[Int, String]类型,但是结果还是能匹配上,这里任意的Map类型都可以匹配成功。泛型擦除如果出现,编译器都会提示警告信息,所以大家看到泛型擦除的警告信息一定要检查一下,以免遗留BUG。在泛型的擦除问题中,数组Array是一个例外,因为数组在Java或Scala中都进行了特殊处理。
def match1(p: Any): String = { p match { case map: List[String] => "List[String]" case _ => "no" } } def main(args: Array[String]): Unit = { println(match1(List(1))) }这里数组的类型可以正确匹配。
最后介绍一下模式匹配中的变量绑定
用@符号设置绑定变量,相当于 val dog = Dog(“dog”, _),这样后面就可以使用dog访问Person的第二个参数。
参考资料:
《Scala编程–综合进阶向导》 http://www.scala-lang.org/