Spark零基础实战 第4章 Scala模式匹配、类型系统彻底精通

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/myvanguard/article/details/86636584

第4章 Scala模式匹配、类型系统彻底精通

本章将介绍Scala模式匹配、类型系统的具体内容。

4.1模式匹配语法

模式匹配包括替代的序列,每句开始使用关键字case。一个箭头符号“=>”分开的表达模式。
语法结构:

var match {
case n=>执行语句Case n执行语句
case _=>执行语句/下划线表示通配符
}

4.2.1模式匹配基础实战

object ObjectSwitch {

    def main(args: Array[String]): Unit = {
        var data = "Spark"
        data match {
            case "Spark"=>println("Spark")
            case _=>println("Nothing")//不匹配任何类型时输出Nothing
        }


    }
    def biData(data:String): Unit ={
        data match{
            case "Spark"=>println("Spark")
                /*if守卫与变量的使用*/
            case data12 if data12 =="Flink"=>println("FLink")
            case _ =>println("others")
        }
    }

    /*类型匹配*/
    def mathType(p:Person): Unit ={
        case stu:Student =>"I am a student!"
        case worker: Worker=>"I am a worker"
        case _ =>println("Nothing")
    }
}

4.2.2 数组、元祖实战

//匹配数组
    def matchArray(array:Array[String])={
        array match{
            case Array("Scala")=>println("Scala")
            case Array(spark,hadoop,storm)=>println("spark+hadoop+storm")
            case Array("Spark",_*)=>println("Spark")
            case _ => println("Nothing")
        }
    }
    //
    def dataTuple(tuple:Tuple2[Any,Any]): Unit ={
        tuple match {
            case (0,_)=>println("0 is matched")
            case (y,0)=>println(y+"0")
            case (x,y)=>println(x+" "+y)
        }

    }

4.2.3 Option实战

 def dataOption(x:Option[String]) = x match {
        case Some(s)=>s//匹配到Option子类some
        case None => "Nothing"//匹配到Option子类None
    }

4.2.4 提取器

提取器是指定义了unapply方法的object。
unapply方法接受一个数据类型,返回另一数据类型,表示可以把入参的数据解构为返回的数据。

object ExtractorTest2 {

    def main(args: Array[String]): Unit = {
        val x = ExtractorTest2(5)
        println(x)
        x match {
            case ExtractorTest2(num)=>println("x bigger")
            case _ => println("i cannot calculate")
        }
    }

    def apply(x:Int) = x*2

    def unapply(z:Int): Option[Int] = if(z%2 ==0)Some(z/2)else None

}

4.2.5 Scala异常处理与模式匹配

import java.io.{FileReader,FileNotFoundException,IOException}
object ExceptionTest {

    def main(args: Array[String]): Unit = {
        try{
            val f =new FileReader("c://1.txt")
        }catch{
            case ex:FileNotFoundException => "Missing file exception"
            case ex:IOException => "Io Exception"
        }finally {
            println("Exiting finally")
        }


    }

}

4.2.6 sealed 密封类

如果在声明超类(父类)时,加上sealed关键字,则超类就成为密封类。
密封类的好处是在做模式匹配时,编译器会自动帮助检查所有匹配项是否已完全包含。
要想添加一个匹配项,必须要写到密封类所在的里面。

//把Person类声明为密封类,则其子类都必须声明在与密封类相同的文件里。
Sealed class Person{
    case class  Worker extends Person
    case class Student extends Person
    def matchType(p:Person)=>{
        p match {
            case stu:Student => println("student")
            case worker:Worker => println("worker")
            case _ => println("Nothing")
        }
    }
}

4.3类型系统

4.3.1泛型

泛型就是定义以类型为参数的类或接口(Scala中为特质)的功能,在Scala中类和特质都可以带类型参数,用方括号来定义类型参数。

//泛型类
class Person[T](val content:T){
    def getContent(id:T)=id+"_"+content
}
//在创建对象时已经指定了T为String类型
val p = new Person[String]("Spark")
p.getContent("Scala")

//泛型函数
def getElem[T](list:List[T]) = list(list.length-1)

4.3.2边界

泛型为Scala扩展了类及函数的复用性,但有时后也需要对泛型做限制。类型限制有类型界定,视图界定,上下文界定等。

类型界定

// T <: 上边界
class Test[T <:Comparable[T]](val first:T,val second:T){
    def bigger = if(first.compareTo(second)<0)second else first
}
// T >:下边界
class Consumer[T](t:T){
	def use[U>:T](u:U)={println(u)}
}

定义了T的上界Comparable,也就是说T必须是Comparable的子类。很显然不能指定T为Int 或File类型,因为在Scala中他们都不是Comparable的子类。

视图界定
类型界定中控制了T的上下界,但是当传入Int类型时,编译报错,因为Int不是上界Comparable的子类,解决办法是"视图界定"。视图界定的标识符"<%"。

// 视图界定
class Test[T <% Comparable[T]](val first:T,val second:T){
    def bigger = if(first.compareTo(second)<0)second else first
}
//Ordered特质
class Test[T <% Ordered[T]](val first:T,val second:T){
	def bigger=if(first<second)second else first
}

Scala就利用Ordered特质解决了大小比较这个问题。
注意:视图界定T<%Ordered[T],要求必须存在一个T到Ordered[T]隐式转换

4.3.3协变与逆变
"+“表示协变,而”-"表示逆变。
C[+T]:如果A是B的子类,那么C[A]是C[B]的子类。
C[-T]:如果A是B的子类,那么C[B]是C[A]的子类。
C[T]:无论A和B是什么关系,C[A]和C[B]没有从属关系。

协变

trait Person[+T]{
    def eat
}
val children = new Person[String]{
    override def eat ={
        println("eat")
    }
}
val father:Person[Any]=children
val action:Any= father.eat

Any是所有类的基类。
协变是正向扩展的,返回对象必然被声明对象兼容

逆变

trait Person[-]{
    def eat
}
val father = new Person[Any]{
    override  def eat = {println("eat")}
}
val children:Person[String]= father
val action:Any = children.eat
//val action:String=children.eat会报类型不匹配

逆变是反向收缩的。实际处理类型比声明类型范围粗略,则返回对象必然会成为声明对象的兄弟对象,不能处理。
因为Any的范围比String的范围粗略,声明对象的类型不能是返回值类型的兄弟对象,否则报错。

猜你喜欢

转载自blog.csdn.net/myvanguard/article/details/86636584