永秀 發表於 2020-6-29 11:04:20

浅谈Scala模式匹配

<p><span style="color: #ff0000"><strong>一.scala模式匹配(pattern matching)</strong></span></p>
<p>pattern matching可以说是scala中十分强大的一个语言特性,当然这不是scala独有的,但这不妨碍它成为scala的语言的一大利器。</p>
<p>scala的pattern matching是类似这样的,</p>
<div class="jb51code">
<pre class="brush:scala;">
e match {
case Pattern1 =&gt; do Something
case Pattern2 if-clause =&gt; do others
...
}</pre>
</div>
<p>其中,变量e后面接一个match以及一个代码块,其中每个case对应一种可能回匹配的类型,如果匹配成功则执行=&gt;后面的代码。</p>
<p>我们可以用一个具体一些的例子来看看模式匹配是怎么工作的:</p>
<div class="jb51code">
<pre class="brush:scala;">
case class Player(name: String, score: Int)
def printMessage(player: Player) = player match {
case Player(_, score) if score &gt; 100000 =&gt;
println("Get a job, dude!")
case Player(name, _) =&gt;
println("Hey, $name, nice to see you again!")
}</pre>
</div>
<p>看起来有点类似于其他语言的switch,但其实还是有很大的不同的。</p>
<p>以java的switch为例,java的switch仅仅会做一些基本类型的匹配,然后执行一些动作,并且是没有返回值的。</p>
<p>而scala的pattern matching match则要强大得多,除了可以匹配数值,同时它还能匹配类型。</p>
<div class="jb51code">
<pre class="brush:scala;">
def parseArgument(arg: String) = arg match {
//匹配值
case "-h" | "--help" =&gt; displayHelp
case "-v" | "--version" =&gt; displayVerion
case whatever =&gt; unknownArgument(whatever)
}</pre>
<div class="jb51code">
<pre class="brush:scala;">
def f(x: Any): String = x match {
//匹配类型
case i:Int =&gt; "integer: " + i
case _:Double =&gt; "a double"
case s:String =&gt; "I want to say " + s
}</pre>
</div>
</div>
<p>同时pattern matching是有返回值的,比如上面的match,它返回的就是一个Unit。我们也可以修改上面的代码让它返回一个字符串:</p>
<div class="jb51code">
<pre class="brush:scala;">
case class Player(name: String, score: Int)
def message(player: Player) = player match {
case Player(_, score) if score &gt; 100000 =&gt;
"Get a job, dude!"
case Player(name, _) =&gt;
"Hey, $name, nice to see you again!"
}</pre>
</div>
<p>值得一提的是,pattern matching 返回值是由第一个匹配的模式中的代码块决定的。</p>
<p><span style="color: #ff0000"><strong>二. 为什么要用pattern matching<br />
</strong></span></p>
<p>看到这里你会发现一个问题,pattern matching不是和if else差不多吗?那为什么还要使用pattern matching呢?</p>
<p>首先我们需要明白,模式匹配其实本质上是提供一个方便的解构(Destructuring)数据结构的方式,以scala为例,pattern matching其实用到了scala中提取器的功能,提取器其实就是类中的unapply()方法。</p>
<div class="jb51code">
<pre class="brush:scala;">
trait User {
def name: String
}
class FreeUser(val name: String) extends User
object FreeUser {
//提取器
def unapply(user: FreeUser): Option = Some(user.name)
}</pre>
<div class="jb51code">
<pre class="brush:scala;">
val user: User = new FreeUser("Daniel")
user match {
case FreeUser(name) =&gt; println("it match here" + name)
case _ =&gt; println("not me")
}</pre>
</div>
</div>
<p>明白了模式匹配的本质你就会直到,其实if else只是pattern matching中的一个典型的用法,但并非它的全部。</p>
<p>同时,pattern matching允许你解耦两个并不真正属于彼此的东西,也使得你的代码更易于测试。比如上面的match部分的代码我们可以写成下面这样:</p>
<div class="jb51code">
<pre class="brush:scala;">
val user: User = new FreeUser("Daniel")
//将返回结果存在一个常量中
val message = user match {
case FreeUser(name) =&gt; "it match here" + name
case _ =&gt; "not me"
}
//可以随意使用该常量,实现解耦
println(message)</pre>
</div>
<p>这样会赋予代码更多的灵活性,同时也更加方便做进一步操作。</p>
<p>而以可读性的角度来说,使用一大堆的if else代码无疑是比较难看的,而如果使用pattern matching的话,代码会简洁清晰很多,而简洁的代码则会更容易阅读。</p>
<p>以上就是浅谈Scala模式匹配的详细内容,更多关于scala模式匹配的资料请关注琼殿技术社区其它相关文章!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>Scala中正则表达式以及与模式匹配结合(多种方式)</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: 浅谈Scala模式匹配