15_Scala_模式匹配下_对象_样例类_匹配嵌套结构_密封类
对象匹配
case中对象的unapply方法(对象提取器) 返回Some集合则为匹配成功 ;返回none集合则为匹配失败
1 构建对象时apply会被调用 ,比如 val n1 = Square(5)
2 当将 Square(n) 写在 case 后时[case Square(n) => xxx],会默认调用unapply 方法(对象提取器)
3 number 会被 传递给def unapply(z: Double) 的 z 形参
4 如果返回的是Some集合,则unapply提取器返回的结果会返回给 n 这个形参
5 case中对象的unapply方法(提取器)返回some集合则为匹配成功
6 返回none集合则为匹配失败
7 当case 后面的对象提取器方法的参数为多个,则会默认调用def unapplySeq() 方法
8 如果unapplySeq返回是Some,获取其中的值,判断得到的sequence中的元素的个数,如果是三个,则把三个元素分别取出,赋值给f1 f2 和f3
object MatchObjectTest {
def main(args: Array[String]): Unit = {
var num: Double = Square(5)
val namesString = "Alex:Bob:Sumi" //字符串
val name2 = namesString.split(":")
// println( name2.getClass + " : " + name2.mkString ) //[Ljava.lang.String
// for (i <- name2){println(i )}
// 执行 num match { case Square(a)}
// 1 调用 unapply(arg: Double) 将 num传入,返回Some(math.sqrt(arg)) 例 Some(6)
// 2 将返回值 6 给 a
// 3 如果没有匹配到 返回None
num match {
case Square(a) => println(a)
case _ => println("啥也不是 完蛋")
}
// 当执行 case Names(n1, n2, n3)
// 1. 会调用 unapplySeq(str),把 "Alex:Bob:Sumi"传入给 str
// 2. 如果 返回的是 Some("Alex:Bob:Sumi"),分别给 (n1, n2, n3)
// 注意,这里的返回的值的个数需要和(n1, n2, n3)要一样
// 3. 如果返回的None ,表示匹配失败
namesString match {
case Names(n1, n2, n3) => println(s"$n1 $n2 $n3")
case _ => println("啥也不是 完蛋")
}
}
}
object Square {
def unapply(arg: Double): Option[Double] = { //拆解对象,对象提前器
println("this is " + arg)
//1. unapply方法是对象提取器 ; 接收arg:Double 类型 返回类型是Option[Double]
//2. 返回的值是 Some(math.sqrt(arg)) 返回arg的开平方的值,并放入到Some(x)
Some(math.sqrt(arg))
}
def apply(arg: Double): Double = arg * arg //构造对象
}
object Names {
//当构造器是多个参数时,就会触发这个对象提取器
def unapplySeq(str: String): Option[Seq[String]] = {
if (str.contains(":")) Some(str.split(":"))
else None
}
}
样例类( 模板类 )
object Casedemo1 {
def main(args: Array[String]): Unit = {
for (item <- Array(Dollar(999.0), Currency(888.0, "RMB"), NoAmount)){
val result = item match {
// case Dollar(a) 1 调用Dollar 底层 unapply(999.0) 2 返回some(999.0) 3 a = 999.0 ; 4("usd" ,999)
case Dollar(a) => ("usd", a )
case Currency(a, b) => (b, a) //unapply(888.0, "RMB") => some(888.0, "RMB") => (a,b) =>(b,a)
case NoAmount => "啥也不是 完蛋"
}
//Dollar(999.0)-> (usd,999.0) //Currency(888.0,RMB)-> (RMB,888.0) NoAmount-> 啥也不是 完蛋
println(item + "-> " + result )
}}}
// 样例类
abstract class Amount
case class Dollar(value: Double) extends Amount //样例类
case class Currency(value: Double, unit: String) extends Amount //样例类
case object NoAmount extends Amount //样例类
Details
1 样例类仍然是类, 用case关键字进行声明, 为模式匹配而优化的类
2 构造器中的参数都成为val ——除非它被显式地声明为var(不建议) //底层对应private final double value;
3 在样例类对应的伴生对象中提供apply方法让 ,不用new关键字 就能构造出相应的对象 ,提供unapply方法让模式匹配可以工作
4 将自动生成toString、equals、hashCode和copy方法(有点类似模板类,直接给生成,供程序员使用)
5 可以添加方法和字段,扩展它们
6 样例类的copy方法和带名参数 (copy创建一个与现有对象值相同的新对象 并可以通过带名参数来修改某些属性)
object Casedemo2 {
def main(args: Array[String]): Unit = {
//样例类的copy方法和带名参数
//copy创建一个与现有对象值相同的新对象,并可以通过带名参数来修改某些属性
//克隆 样例类的copy方法和带名参数
val d1 = Dollar2(20.0)
val d2_clone = d1.copy() // 克隆,创建的对象和d1的属性一样
val d3_clone = d1.copy(200) // 可以通过 参数来修改某些属性值
println(d2_clone + "->"+ d2_clone.value) //能直接打印d2_clone because 重写了toString
println(d3_clone + "->"+ d3_clone.value)
}}
abstract class Amount2
case class Dollar2(value: Double) extends Amount2 //样例类
case class Currency2(value: Double, unit: String) extends Amount2 //样例类
case object NoAmount2 extends Amount2 //样例类
中置表达式 1 + 2 操作符是以中缀形式处于操作数的中间(例:3 + 4)
如果unapply方法产出一个元组,可以在case语句中使用中置表示法 (匹配List 序列)
object Casedemo3 {
def main(args: Array[String]): Unit = {
// 中置表达式 1 + 2 操作符是以中缀形式处于操作数的中间(例:3 + 4)
// 如果unapply方法产出一个元组,可以在case语句中使用中置表示法
List(1, 3, 5, 9) match {
//1.两个元素间::叫中置表达式,至少first,second两个匹配才行.
//2.first 匹配第一个 second 匹配第二个, rest 匹配剩余部分(5,9)
// 1 3 2 List(5,9)
case first :: second :: rest => println(first + " " + second + " "+ rest.length + " " + rest)
case _ => println("匹配不到...")
}
}}
匹配嵌套结构操作原理类似于正则表达式
object SaleTest1 {
def main(args: Array[String]): Unit = {
var sales1 = Bundle2("书籍", 10, Book2("漫画", 40), Bundle2("文学作品", 20, Book2("《阳关》", 80), Book2("《围城》", 30)))
//1 使用case语句,得到 "漫画"
//如果我们进行对象匹配时,不想接受某些值,则使用_ 忽略即可,_* 表示所有
val result1 = sales1 match {
case Bundle2(_,_,Book2(desc,_), _*) => desc
}
// println(result1)
//2 使用 @ 表示将嵌套的值绑定到变量, _* 绑定剩余 item 到 others
val result2 = sales1 match {
case Bundle2(_,_, shu @ Book2(_,_), others @ _*) => (shu, others)
}
//(Book2(漫画,40),WrappedArray(Bundle2(文学作品,20,WrappedArray(Book2(《阳关》,80), Book2(《围城》,30)))))
// println(result2)
//3 不使用_*绑定剩余Item 到 others
val result3 = sales1 match {
case Bundle2(_,_, shu @ Book2(_,_), others) => (shu, others)
}
//(Book2(漫画,40),Bundle2(文学作品,20,WrappedArray(Book2(《阳关》,80), Book2(《围城》,30))))
println(result3)
}}
abstract class Items2
case class Book2(information: String, price: Int) extends Items2
case class Bundle2(information: String, discount: Int, items: Items2*) extends Items2
如果一个类 仅仅想在当前文件用,就使用sealed 类
object SalesTest {
def main(args: Array[String]): Unit = {
//, Book("天龙八部", 100)
var sales1 = Bundle("书籍", 10 ,Book("漫画", 40) , Bundle("文学作品", 20, Book("《阳关》", 80), Book("《围城》", 30)))
val result = sales1 match {
// case Bundle(_, _, Book(name, _), _*) => name
case Bundle(_,_, b1 @ Book(_,_), b2 @ _) => (b1,b2) //ArraySeq
case _ => "啥也不是"
}
// println(result)
val result_1 = count_price(sales1)
println(result_1)
}
def count_price (b: Items): Int={
b match {
case Book(_, price1) => price1
case Bundle(_, discount_price, others @ _*) => others.map(count_price).sum - discount_price
}
}
}
//密封类
abstract sealed class Items
case class Book(information: String, price : Int ) extends Items
case class Bundle(information: String ,discount: Int, item: Items*) extends Items
- 点赞
- 收藏
- 关注作者
评论(0)