15_Scala_模式匹配下_对象_样例类_匹配嵌套结构_密封类

举报
alexsully 发表于 2021/04/23 18:30:26 2021/04/23
【摘要】 1 对象匹配 2 样板模板例 case class 3 中置表达式 4 匹配嵌套结构 5 密封类 sealed

对象匹配
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
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。