scala学习(3)-模式匹配与隐式转换

一、模式匹配

1、采用match关键字声明,每个分支采用case关键字进行声明,当要匹配时会从第一个case分支开始,如果匹配成功,那么执行对应逻辑代码,如果匹配失败,继续执行下一个分支判断,如果所有case都不匹配,那么会执行case_分支。

2、模式守卫,如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫。

package chapter01

object PatternMatchCase {

  def main(args: Array[String]): Unit = {

    val x = 2
    val y = x match {
      case 1 => "one"
      case 2 => "two"
      case _ => "other"
    }

    val a = 25
    val b = 90
    def matchOp(op: Char): Any = op match {
      case '+' => a+b
      case '-' => a-b
      case _ => "输入非法"
    }
    println(matchOp('+'))

    //模式守卫
    def abs(num: Int): Int = {
      num match {
        case i if i >= 0 => i
        case i if i < 0 => -i
      }
    }


  }

}

3、匹配不同类型

package chapter01

object MatchTypes {

  def main(args: Array[String]): Unit = {
    //1、匹配常量
    def describeConst(x: Any): String = x match {
      case 1 => "number one"
      case "hello" => "hello string"
      case true => "true boolean"
      case _ => ""
    }

    //2、匹配类型
    def desctibeType(x: Any): String = x match {
      case i: Int => "Int" + i
      case list: List[String] => "List[String]" + list //List[Int]也会匹配到,存在泛型擦除
      case array: Array[int] => "Array[int]" + array.mkString(",") //Array[Int]不会匹配到,不存在泛型擦除
      case a => "Something else " + a //获取当前变量,不知道什么类型
    }
    //3、匹配数组
    for (arr <- List(
      Array(0),
      Array(1, 0),
      Array(0, 1, 0),
      Array("hello", 2, 3)
    )) {
      val result = arr match {
        case Array(0) => "0"
        case Array(x, y) => "Array: " + x + "," + y
        case Array(0, _*) => "以0开头的数组"
        case Array(x, 1, y) => "中间为1的数组"
        case _ => "something else"
      }
    }
    //4、匹配列表-方式一
    for (list <- List(
      List(0),
      List(1, 0),
      List(0, 1, 0),
      List("hello", 2, 3)
    )) {
      val result = list match {
        case List(0) => "0"
        case List(x, y) => "List: " + x + "," + y
        case List(0, _*) => "以0开头的列表"
        case List(x, 1, y) => "中间为1的列表"
        case _ => "something else"
      }
    }
    //4、匹配列表-方式二
    val list1 = List(1, 2, 3, 4, 5)
    list1 match {
      case first :: second :: rest => println(s"first: $first, second: #second: $second, rese: $rest")
      case _ => println("something else")
    }
    //for推导式进行模式匹配
    val list3: List[(String, Int)] = List(("a", 12), ("b", 3), ("c", 7))
    for (elem <- list3) {
      println(elem._1 + " " + elem._2)
    }
    for ((word, count) <- list3) {
      println(word + " " + count)
    }
    for (("a", count) <- list3) {
      println("a" + " " + count)
    }
    //匹配类的对象实例
    val student = new Student("alice", 12)
    val result = student match {
      case Student("alice", 12) => "Alice 12"
      case _ => "Else"
    }
  }
}

class Student(val name: String, val age: Int)
object Student {
  //实现装箱拆箱方法
  def apply(name: String, age: Int): Student = new Student(name, age)
  //必须实现一个unapply方法,用来对对象属性进行拆解
  def unapply(arg: Student): Option[(String, Int)] = {
    if (arg == null){
      None
    }else{
      Some((arg.name, arg.age))
    }
  }
}

//定义样例类,直接匹配,不需要实现装拆箱
case class Student11(name: String, age: Int)


二、偏函数

        偏函数也是函数的一种,通过偏函数可以方便的对输入参数做更精确的检查,例如该偏函数的输入类型为List[Int],而我们需要的是第一个元素是0的集合,这就是通过模式匹配实现的。

package chapter01

object PartitialFunctionTest {


  def main(args: Array[String]): Unit = {

    val list:List[(String, Int)] = List(("a", 12), ("b", 13))

    //1、map转换将value*2
    val newList = list.map(tuple => (tuple._1, tuple._2 * 2))
    //2、用模式匹配对元组元素赋值
    val newList2 = list.map(
      tuple => {
        tuple match {
          case (word, count) => (word, count * 2)
        }
      }
    )
    //3、省略lambda表达式的写法,即偏函数
    val newList3 = list.map {
      case (word, count) => (word, count * 2)
    }
    //偏函数的应用-求绝对值
    //针对数据分为不同情形:正负零
    val positiveAbs:PartialFunction[Int, Int] = {
      case x if x > 0 => x
    }
    val negativeAbs:PartialFunction[Int, Int] = {
      case x if x < 0 => -x
    }
    val zeroAbs:PartialFunction[Int, Int] = {
      case 0 => 0
    }
    //组合起来
    def abs(x: Int): Int = positiveAbs.orElse(negativeAbs).orElse(zeroAbs)(x)
  }

}
三、异常处理
package chapter01

object ExceptionTest {

  def main(args: Array[String]): Unit = {
    
    try{
      val n = 10 /0
    }catch{
      case e:ArithmeticException =>{
        println("发生算数异常")
      }
      case e: Exception => {
        println("发生一般异常")
      }
    }finally {
      println("处理结束")
    }
    
  }

}
四、隐式转换

        当编译器第一次编译失败的时候,会在当前环境中查找能让代码编译通过的方法,用于将类型进行转换,实现二次编译。隐式转换可以在不需要改任何代码的情况下,扩展某个类的功能。

package chapter01

object ImplicitTest {

  def main(args: Array[String]): Unit = {

    //隐式函数
    implicit def convert(num: Int): MyRIchInt = new MyRIchInt(num)
    println(12.myMax(15))

    //隐式类
//    implicit class MyRIchInt(val self: Int){
//      def myMax(n: Int): Int = if(n < self) self else n
//      def myMin(n: Int): Int = if (n < self) n else self
//    }

    //隐式参数,同一作用域范围内同一类型只能有一个隐式值
    implicit val str:String = "alice"
    implicit val age:Int = 19
    def sayHello(implicit name: String): Unit = {
      println("hello:" + name)
    }
    def sayHi(name: String = "alice"): Unit = {
      println("hi:" + name)
    }
//    sayHello()
    sayHello
    def hiAge(): Unit = {
      println("hi, " + implicitly[Int])
    }
    hiAge()
  }

}

class MyRIchInt(val self: Int){
  def myMax(n: Int): Int = if(n < self) self else n
  def myMin(n: Int): Int = if (n < self) n else self
}
五、泛型
package chapter01

class GenericsTest {

  def main(args: Array[String]): Unit = {
    //协变和逆变
    val child: Parent = new Child
    val childList: MyCollection[Parent] = new MyCollection[Parent]
    val childList1: MyCollection[Parent] = new MyCollection[Child]
    val childList2: MyCollection1[SubChild] = new MyCollection1[Child]

    //泛型的上下限
    def test[A <: Child](a: A): Unit = {
      println(a.getClass.getName)
    }
//    test[Parent](new Child)//报错,上限为Child
    test[Child](new SubChild)

  }

}
class Parent {}
class Child extends Parent{}
class SubChild extends Child{}

class MyCollection[+E]{}
class MyCollection1[-E]{}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值