Scala之模式匹配和样例类

2024-04-30 12:38

本文主要是介绍Scala之模式匹配和样例类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 模式匹配

1.1. 更好的 Switch

Scala 中类似 Java 的 switch 代码:

object PatternDemo {def main(args: Array[String]): Unit = {var sign = 0val ch: Char  = 'p'val valchar = 'p'var digit = 0//match 是表达式ch match {case '+' => sign = 1case '-' => sign = -1//使用|分割多个选项case '*' | 'x' => sign = 2//可以使用变量case valchar => sign = 3//case _ 类似Java中的default// 如果没有模式能匹配,会抛出MacthError//可以给模式添加守卫case _ if Character.isDigit(ch) => digit = Character.digit(ch, 10)}println("sign = "+ sign)}}

1.2. 样例类匹配

//定义样例类
abstract class Notification
case class Email(sender: String, title: String, body: String) extends Notification
case class SMS(caller: String, message: String) extends Notification
case class VoiceRecording(contactName: String, link: String) extends Notification//基于样例类的模式匹配
def showNotification(notification: Notification): String = {notification match {case Email(email, title, _) =>s"You got an email from $email with title: $title"case SMS(number, message) =>s"You got an SMS from $number! Message: $message"case VoiceRecording(name, link) =>s"you received a Voice Recording from $name! Click the link to hear it: $link"}
}
val someSms = SMS("12345", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
println(showNotification(someSms))  //结果:You got an SMS from 12345! Message: Are you there?
println(showNotification(someVoiceRecording))  //结果:you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123

1.3. 带守卫的模式

增加布尔表达式使得匹配更具体。

def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {notification match {//仅匹配email在importantPeople列表里的内容case Email(email, _, _) if importantPeopleInfo.contains(email) =>"You got an email from special someone!"case SMS(number, _) if importantPeopleInfo.contains(number) =>"You got an SMS from special someone!"case other =>showNotification(other) // nothing special, delegate to our original showNotification function}
}val importantPeopleInfo = Seq("867-5309", "jenny@gmail.com")val someSms = SMS("867-5309", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
val importantEmail = Email("jenny@gmail.com", "Drinks tonight?", "I'm free after 5!")
val importantSms = SMS("867-5309", "I'm here! Where are you?")println(showImportantNotification(someSms, importantPeopleInfo))
println(showImportantNotification(someVoiceRecording, importantPeopleInfo))
println(showImportantNotification(importantEmail, importantPeopleInfo))
println(showImportantNotification(importantSms, importantPeopleInfo))

1.4. 类型匹配

val arr = Array("hello", 1, 2.0, 'a')
val obj = arr(Random.nextInt(4))
obj match {case x: Int => xcase s: String => Integer.parseInt(s)case _: BigInt => Int.MaxValuecase _ => 0
}

1.5. 匹配数组、列表、元组

数组匹配

val arr1 = Array(1,1)val res = arr1 match {case Array(0) => "0"//匹配包含0的数组case Array(x, y) => s"$x $y"// 匹配任何带有两个元素的数组,并将元素绑定到x和ycase Array(0, _*) => "0..."//匹配任何以0开始的数组case _ => "something else"
}

列表匹配

val lst = List(1,2)
val res2 =  list match {case 0 :: Nil => "0"case x :: y :: Nil => x + " " + ycase 0 :: tail => "0 ..."case _ => "something else"}

元组匹配

var pair = (1,2)
val res3 =  pair match {case (0, _)  => "0 ..."case (y, 0) => s"$y 0"case _ => "neither is 0"
}

2. Sealed 类 (密封类)

Scala 中,Traits 和 class 可以被关键字 Sealed 修饰,被该关键字修饰后,它所有的子类都必须在同一文件中被定义。

sealed abstract class Furniture
case class Couch() extends Furniture
case class Chair() extends Furniture
//此时无需定义能匹配所有的类型了
def findPlaceToSit(piece: Furniture): String = piece match {case a: Couch => "Lie on the couch"case b: Chair => "Sit on the chair"
}

3. 样例类

在 Scala 中样例类是一中特殊的类,样例类是不可变的,可以通过值进行比较,可用于模式匹配。
定义一个样例类:

case class Point(x: Int, y: Int)

创建样例类对象:

val point = Point(1, 2)
val anotherPoint = Point(1, 2)
val yetAnotherPoint = Point(2, 2)

通过值对样例类对象进行比较:

if (point == anotherPoint) {println(point + " and " + anotherPoint + " are the same.")
} else {println(point + " and " + anotherPoint + " are different.")
}
// Point(1,2) 和 Point(1,2)一样的.if (point == yetAnotherPoint) {println(point + " and " + yetAnotherPoint + " are the same.")
} else {println(point + " and " + yetAnotherPoint + " are different.")
}
// Point(1,2)和Point(2,2)是不同的.

在模式匹配中使用样例类:

abstract class Amount
// 继承了普通类的两个样例类
case class Dollar(value: Double) extends Amount
case class Currency(value: Double, unit: String) extends Amount
case object Nothing extends Amount
object CaseClassDemo {def main(args: Array[String]): Unit = {val amt = new Dollar(10);patternMatch(amt)}def patternMatch(amt: Amount) {amt match {case Dollar(v) => println("$" + v)case Currency(_, u) => println("Oh noes, I got " + u)case Nothing => println("nothing") //样例对象没有()}}
}

声明样例类 ,以下几件事会自动发生:

(1) 构造器中每一个参数都是 val,除非显示地声明为 var  
(2) 伴生对象提供 apply ,让你不使用 new 关键字就能构造出相应的对象
(3) 提供 unapply 方法,让模式匹配可以工作  
(4) 生成 toString,equals,hashCode,copy 方法,除非显示给出这些方法的定义。

4. Option 类型

在 Scala 中 Option 类型样例类用来表示可能存在或也可能不存在的值( Option 的子类有 Some 和 None )。Some 包装了某个值,None 表示没有值。

object OptionDemo {def main(args: Array[String]) {val map = Map("a" -> 1, "b" -> 2)val v = map.get("b") match {case Some(i) => icase None => 0}println(v)//更好的方式val v1 = map.getOrElse("c", 0)println(v1)}
}

5. 偏函数

被包在花括号内没有 match 的一组 case 语句是一个偏函数,它是 PartialFunction[A, B] 的一个实例,A 代表参数类型,B 代表返回类型,常用作输入模式匹配。

object PartialFunctionDemo {def f: PartialFunction[String, Int] = {case "one" => 1case "two" => 2// case _ => -1}def main(args: Array[String]) {//调用f.apply("one")println(f("one"))println(f.isDefinedAt("three"))//抛出MatchErrorprintln(f("three"))}
}

这篇关于Scala之模式匹配和样例类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/948884

相关文章

【scala 安装错误】错误: 找不到或无法加载主类 scala.tools.nsc.MainGenericRunner

错误: 找不到或无法加载主类 scala.tools.nsc.MainGenericRunner 原因: Scala安装路径中包含空格。 解决办法:scala 不要安装在E:\Program Files 这种有空格的目录下,简直坑

Scala模式匹配下提取器构造

示例代码: object :> {def unapply[A] (list:List[A]) = {Some( (list.init,list.last) )}}object Extractor_Advanced {def main(args: Array[String]): Unit = {(1 to 9).toList match{ case _ :> 9 => println(

从spark源码的角度思考scala中的模式匹配

1.scala中模式匹配 2.spark源码中的模式匹配思考 spark中master会收到worker发过来的akka的消息, 此消息是case class即(Master.class中): case class RegisterWorker(id:String,host:String,port:Int,cores:Int,memory:Int,webUiPort:int

Scala界面事件处理

示例代码: import scala.swing.SimpleSwingApplicationimport scala.swing.MainFrameimport scala.swing.Buttonimport scala.swing.Labelimport scala.swing.Orientationimport scala.swing.BoxPanelimpo

Scala界面Panel、Layout初探

示例代码: package com.dt.scala.guiimport scala.swing.SimpleSwingApplicationimport scala.swing.MainFrameimport scala.swing.Buttonimport scala.swing.Labelimport scala.swing.Orientationimport scal

scala界面GUI编程实战初步了解

示例代码: import scala.swing._//SimpleSwingApplication继承自SwingApplication类(此类中有main方法,因此可以运行显示界面)object Hello_GUI extends SimpleSwingApplication {def top = new MainFrame{ //顶级容器title = "Hello GUI"co

Scala并发编程react、loop代码实战详解

示例代码及注释: //scala并发编程中的react和loop,共同特点://通过线程存用的方式让性能有所提升。//Actor本身的运行,被actor子系统管理的时候,会有一个或者多个远程的线程让当前的actor使用//一般情况下每个Actor都有自己的线程。只有有自己的线程时,我们的Actor中的actor方法才会执行。//但是,这样线程的开销会非常大,所以为了共用线

scala并发编程原生线程Actor、Case Class下的消息传递和偏函数实战

参考代码: import scala.actors._case class Person(name:String,age:Int)class HelloActor extends Actor{def act(){while(true){receive{case Person(name,age)=>{ //偏函数println("Name: "+ name + ":" +"Age:"

scala基础概念

Scala是面向行的语言,Scala 语句末尾的分号写或者不写都可以。 对象 - 对象有属性和行为。例如:一只哈士奇的属性有:颜色,名字,行为有:叫、跑、吃等。对象是一个类的实例。 类 - 类是对象的抽象;对象是类的具体实例。 方法 - 方法描述的基本的行为,一个类可以包含多个方法。 字段 - 每个对象都有它唯一的实例变量集合,即字段。对象的属性通过给字段赋值来创建。 基本语法

数据结构串的模式匹配算法--BF暴力匹配

BF(Brute-Force,暴力匹配)算法是一种简单的字符串匹配算法,其基本思想是将目标串S逐个字符与模式串P进行比对,直到找到匹配或遍历完S为止。下面是一个使用C语言实现的BF算法示例: #include <stdio.h> #include <string.h> // BF算法实现 // 参数:text是文本串,pattern是模式串 // 返回值:如果找到模式串,则返回模式