Scala中的模式匹配match

scala中的模式匹配类似与java中的switch语法,但功能比switch更加强大,且能匹配的方式各种各样。

我总结了一下,scala的match的匹配方式有如下几种:

  • 通配模式
  • 常量模式
  • 变量模式
  • 构造器模式
  • 序列模式
  • 元组模式
  • 类型模式

在介绍模式匹配之前,先要介绍一下Scala的样本类,样本类可以在模式匹配中使用,而一般的普通类则不行。

样本类

先来一个样本类的例子:

abstract class Animal
   case class Dog() extends Animal
   case class Person(name: String, age: Int) extends Animal

Scala对样本类添加了一些辅助方法:
1、工厂方法

var p = new Dog()
var p = Dog()

这两句的作用是一样的。
2、样本类的参数被当成字段进行处理

var p = Person("shadon", 28)
p.name
p.age

3、默认实现了toString, hashCode和equals方法

由于以上的三点,因此在使用样本类时非常便利。

通配模式:

person match {
 case Person(name, age) =>
    println("是个人")
 case _ =>
    println("other")
}

匹配person对象,如果是2个参数的则匹配第一个,这个其实是构造器模式,后面会讲到。通配模式的重点在‘_’,表示匹配任意对象。当然通配符‘_’也可以放在类的参数上,用于匹配参数个数,例如:

p match {
 case Person(_, _) =>
    println("person")
 case _ =>
    println("other")
}

常量模式

def match1(p: Any): Unit = {
  p match {
     case 2 =>
        println("number 2")
     case "hell" =>
        println("string hell")
     case Nil =>
        println("null")
     case _ =>
        println("other")
  }
}

常量模式用于匹配常量值,这个好理解。

变量模式

scala认定变量模式的方式比较奇特:用小写字母开头的变量;

def match1(p: Any): String = {
  val pp = Math.PI
  p match {
     case pp => "PI"
  }
}

这里不论传入什么参数,都会被匹配,而且case里面只能使用一个,不然会抛错。如果想将变量模式转变成常量模式只需要增加转义符:`pp`。
思考:这个变量模式我一直想不通,到底有何用途,哪位网友知道请相告知,谢谢!

构造器模式

def match1(p: Any): String = {
  p match {
     case Person("shadon", _) => "shadon"
     case _ => "no"
  }
}

这里匹配第一个参数为“shadon”的Person。

序列模式

def match1(p: Any): String = {
  p match {
     case List(9, _, _) => "9 start"
     case _ => "no"
  }
}

序列模式主要用于匹配像List, Array这样的序列类。使用‘_*’可以匹配零到多个参数。

def match1(p: Any): String = {
  p match {
     case List(9, _, _*) => "9 start"
     case _ => "no"
  }
}

元组模式

def match1(p: Any): String = {
  p match {
     case (_, 1) => "(_, 1)"
     case _ => "no"
  }
}

类型模式

def match1(p: Any): String = {
  p match {
     case a: String => "String a = " + a
     case b: Int => "Int a = " + b
     case c: Boolean => "boolean c = " + c
     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)))
}

这里数组的类型可以正确匹配。

最后介绍一下模式匹配中的变量绑定

变量绑定@

abstract class Animal
   case class Dog(name: String, age: Int) extends Animal
   case class Person(name: String, age: Animal) extends Animal

object MatchDemo {

   def match1(p: Any): String = {
      p match {
         case Person("shadon", dog @ Dog("dog", _)) => "dog = " + dog
         case _ => "no"
      }
   }

   def main(args: Array[String]): Unit = {
      println(match1(Person("shadon", Dog("dog", 1))))
   }

}

用@符号设置绑定变量,相当于 val dog = Dog(“dog”, _),这样后面就可以使用dog访问Person的第二个参数。

参考资料

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shadon178

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值