1:Scala和Java的对比:

1.1:Scala中的函数是Java中完全没有的概念。因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只有方法的概念,即寄存和依赖于类与对象中的方法。Java中的方法是绝对不可能脱离类和对象独立存在的。
1.2:Scala是一门既面向对象,又面向过程的语言。因此在Scala中有非常好的面向对象的特性,可以使用Scala来基于面向对象的思想开发大型复杂的系统和工程,而且Scala也面向过程,因此Scala中有函数的概念。在Scala中,函数和类,对象等一样,都是一等公民。Scala中的函数可以独立存在,不需要依赖于任何类与对象。
1.3:Scala的函数式编程,就是Scala面向过程的最好的佐证。也正是因为函数式编程,才让Scala具备了Java所不具备对的更强大的功能和特性。 而之所以Scala一直没有替换Java,是因为Scala之前一直没有开发过太多知名的应用。而Java则不一样。最重要的一点在于,Java现在不只是一门编程语言,还是一个庞大的,涵盖了软件开发,甚至云计算,大数据的技术生态。其中重要框架和系统包含Spring,lucene,Hadoop,Activiti等等。

2:Scala之函数式编程:

2.1:将函数赋值给变量:    Scala中的函数是一等公民,可以独立定义,独立存在,而且可以直接将函数作为值赋值给变量,必须在函数后面加上空格和下划线:    class Person{

      def hello(name : String) = {        println("hi," + name)      }      //将函数赋值给变量的语法,函数命令 _(1、函数名称,2、空格,3、下划线)      val sayHello = hello _;      sayHello("张三");    }    //定义一个Object来测试    object Object {

      def main(args: Array[String]): Unit = {        val p1 = new Person;        p1.sayHello      }    }2.2:匿名函数:    Scala中,函数也可以不需要命名,此时函数被称为匿名函数。可以直接定义函数之后,将函数赋值给某个变量,也可以将直接定义的匿名函数传入其他函数之中。Scala定义匿名函数的语法规则就是:(参数名称:参数类型) => 函数体;这种语法必须掌握和深刻理解。    class Person{

      val sayHello = (name : String) => println("hi,"+ name);    }    //定义一个Object来测试    object Object {

      def main(args: Array[String]): Unit = {        val p1 = new Person;        p1.sayHello("张三");      }    }2.3:高阶函数:    Scala中,由于函数是一等公民,因此可以直接将某个函数传入其他函数,作为参数。这个功能是及其强大的,也是Java这种面向对象的编程语言所不具备的。    接受其他函数作为参数的函数,也被称作为高阶函数(higher-order function),高阶函数的另一个功能就是将函数作为返回值:    class Person{

      val sayHello = (name : String) => println("hi,"+ name);      //def 函数名称(函数名称:(函数类型) => 函数返回值,参数1 :参数类型......)      def greeting(hello:(String) => Unit, name: String): Unit ={        hello(name);      }    }    //定义一个Object来测试            object Object {

      def main(args: Array[String]): Unit = {        val p1 = new Person;        p1.greeting(p1.sayHello, "李思思");      }    }    //高阶函数的另一个功能就是将函数作为返回值:    class Person{      //高阶函数的另一个功能就是将函数作为返回值:      def getGreetingFunc(msg : String) = (name : String) => println(msg +", " + name);      val greetingFunc = getGreetingFunc("hello");      greetingFunc("张三三");    }    //定义一个Object来测试    object Object {

      def main(args: Array[String]): Unit = {        val p1 = new Person;        p1.greetingFunc;        println(Array(1,2,3,4,5).map((num : Int) => num * num).toBuffer)      }    }2.4:高阶函数的类型推断:    高阶函数可以自动推断出参数类型,而不需要写明类型,而且对于只有一个参数的函数,还可以省去其小括号。如果仅有一个参数在右侧的函数体内只使用一次,则还可以将接受参数省略,并且将参数用_来替代。    class Person{

      //func函数名称作为参数一。name是参数二      def greeting(func:(String) => Unit,name : String) {        func(name)      }      //匿名函数      greeting((name : String) => println("hello," + name) ,"张三");      //高阶函数可以自动推断出参数类型,而不需要写明类型。如这里没有写name的String类型。      greeting((name) => println("hello, "+ name) ,"李思思");      //而且对于只有一个参数的函数,还可以省去其小括号。      greeting(name => println("hello," + name) ,"王五五");

      //如果仅有一个参数在右侧的函数体内只使用一次,则还可以将接受参数省略,并且将参数用_来替代。      def triple(func:(Int) =>Int) ={        func(3)      }

    }    //定义一个Object来测试    object Object {

      def main(args: Array[String]): Unit = {        val p1 = new Person;        println(p1.triple(10 * _))      }    }2.5:Scala的常用的高阶函数:    a、map,对传入的每个元素都进行映射,返回一个处理后的元素:        println(Array(1,2,3,4,5).map(2 * _).toBuffer);    b、foreach,对传入的每个元素都进行处理,但是没有返回值:        (1 to 9).map("*" * _).foreach(println _);    c、filter,对传入的每个元素都进行条件判断,如果对元素返回true,则保留该元素,否则过滤掉该元素:        val a = (1 to 20).filter(_ % 2 ==0);        println(a)    d、reduceLeft,从左侧元素开始,进行reduce操作,即先对元素1和元素2进行处理,然后将结果与元素3处理,再将结果与元素4处理,依次类推,即为reduce:        var a = (1 to 9).reduceLeft(_ * _);        //此操作相当于1*2*3*4*5*6*7*8*9        println(a)    e、sortWith,对元素进行两两相比,进行排序:        var arr = Array(3,2,4,1,5,7).sortWith(_ < _);        println(arr.toBuffer)2.6:闭包:    a、在Java中,不支持直接将函数传入一个方法作为参数,通常来说,唯一的方法就是定义一个实现了某个接口的类的实例对象,该对象只有一个方法。而这些接口都只有单个的抽象方法,也就是single abstract method,简称为SAM;    b、由于Scala是可以调用Java的代码的,因此当我们调用Java的某个方法的时候,可能就不得不创建SAM传递给方法,非常麻烦。但是Scala又是直接传递函数的。此时就可以使用Scala提供的,在调用Java方法的时候,使用的功能。SAM转换,即将SAM转换为Scala函数。(注意:要使用SAM转换为,需要使用Scala提供的特性,隐式转换):    c、闭包,最简洁的解释就是函数在变量不处于其有效作用域的时候,还能够对变量进行访问,即为闭包;        class Person{

          def getGreetingFunc(msg : String) = (name : String) => println(msg + "," + name);          //两次调用getGreetingFunc函数,传入不同的msg,并创建不同的函数返回.          //然而,msg只是一个局部变量,却在getGreetingFunc执行完以后,还可以继承存在创建的函数之中。          //greetingFuncHello("张三"),调用的时候,值为"hello"的msg被保留在了函数体内部,可以反复的使用。          //这种变量超出了其作用域,还可以使用的情况,即为闭包。

          val greetingFuncHello = getGreetingFunc("hello");          val greetingFuncHi = getGreetingFunc("hi");          //Scala通过为每个函数创建对象来实现闭包,实际上对于getGreetingFunc函数创建的函数。msg是作为函数对象的变量存在的。因此每个函数才可以拥有不同的msg          //Scala编译器会确保上述闭包机制。

        }        //定义一个Object来测试        object Object {

          def main(args: Array[String]): Unit = {            val p1 = new Person;            p1.greetingFuncHello("张三三");            p1.greetingFuncHi("李思思");          }        }2.7:SAM转换(Scala函数和Java的类转换):  a、在Java中,不支持直接将函数传入一个方法作为参数,通常来说,唯一的方法就是定义一个实现了某个接口的类的实例对象,该对象只有一个方法。而这些接口都只有单个的抽象方法,也就是single abstract method,简称为SAM;    b、由于Scala是可以调用Java的代码的,因此当我们调用Java的某个方法的时候,可能就不得不创建SAM传递给方法,非常麻烦。但是Scala又是直接传递函数的。此时就可以使用Scala提供的,在调用Java方法的时候,使用的功能。SAM转换,即将SAM转换为Scala函数。(注意:要使用SAM转换为,需要使用Scala提供的特性,隐式转换): 2.8:Currying函数:  Currying函数指的是,将原来接受两个参数的一个函数,转换为两个函数,第一个函数接受原先的第一个参数,然后返回接受原先第二个参数的第二个函数。在函数调用的过程中,就变为了两个函数连续调用的形式:    class Person{

      def sum(a: Int ,b : Int) = a + b;      def sum2(a : Int) = (b : Int) => a+b;      def sum3(a : Int)(b : Int) = a + b;    }    //定义一个Object来测试    object Object {

      def main(args: Array[String]): Unit = {        val p = new Person;        println(p.sum(1,4));        println(p.sum2(2)(2));        println(p.sum3(3)(3));      }    }2.9:return:  Scala中,不需要使用return来返回函数的值,函数最后一行语句的值,就是函数的返回值。在Scala中,return用于在匿名函数中返回值给包含匿名函数的带名函数,并作为带名函数的返回值。使用return的匿名函数,是必须给出返回类型的,否则无法通过编译。    class Person{

      def greeting(name : String) ={        def hello(name : String): String ={           return "hello," + name;        }        hello(name);      }    }            //定义一个Object来测试        object Object {

      def main(args: Array[String]): Unit = {        val p = new Person;        println(p.greeting("李思思"));      }    }

3:Scala函数式编程之集合操作:

3.1:Scala的集合体系结构:Scala中的集合体系主要包括:Iterable,Seq,Set,Map。其中,Iterable是所有集合trait的跟trait。这个结构与Java的集合体系非常相似。Scala中的集合是分成可变和不可变的两类集合的,其中可变集合就是说,集合的元素可以动态修改。而不可变集合的元素在初始化之后,就无法修改了。分别对应scala.collection.mutable和scala.collection.immutable两个包。Scala中的Seq下包含了Range,ArrayBuffer,List等子trait。其中Range就代表了一个序列,通常可以使用"1 to 10"这种语法来产生一个Range。ArrayBuffer就类似于Java中的ArrayList。Scala的集合类的map,flatMap,reduce,reduceLeft,foreach,等这些函数就是高阶函数。可以接受其他函数作为参数。
3.2:List:List代表一个不可变的列表,List的创建,val list = new List(1,2,3,4);List有head和tail,head代表List的第一个元素,tail代表第一个元素以后的所有元素。list.head,list.tail;List有特殊的::操作符,可以用于将head和tail合并成一个List,0::list;3.3:LinkedList:LinkedList代表一个可变的列表,使用elem可以引用其头部,使用next可以引用其尾部。val l = mutable.LinkedList(1,2,3,4,5,6,7);println(l.elem + " " + l.next);
3.4:Set:Set代表一个没有重复元素的集合。将重复元素加入Set是没有用的。而且Set是不保证插入顺序的,也就是说,Set中的元素是乱序的。LinkedHashSet会用一个链表来维护插入顺序。SortedSet会自动根据key来进行排序的。3.5:集合的函数式编程:a、map案例,为List中每个元素都添加一个前缀:val list = List("张三","李思思","王五五").map("name is :" + _);println(list.toBuffer)b、faltMap案例,将List中的多行句子拆分成单词:val list = List("hello world , i am bie xiansheng").flatMap(_.split(" "));println(list.toBuffer)c、foreach案例,打印List中的每个单词:List("hello world , i am bie xiansheng").foreach(println(_));d、zip案例,对学生姓名和学生成绩进行关联:val list = List("张三三","李思思","王五五","赵六六").zip(List("1","2","3","4"));println(list)

4:Scala之模式匹配(mathch case语法,即为模式匹配):

模式匹配是Scala中非常有特色的,非常强大的一种功能。模式匹配,其实类似于Java中的swich case语法,即对一个值进行条件判断,然后针对某种条件,即针对不同的处理。但是Scala的模式匹配功能比Java的swich case语法的功能强大的多,Java的swich case语法只能对值进行匹配。但是Scala的模式匹配除了可以对值进行匹配之外,还可以对类型进行匹配,对Array和List的元素情况进行匹配,对case class进行匹配,甚至对有值或者没值进行匹配。

4.1:模式匹配的基础语法:a、mathch case的语法如下所示:变量 mathch {case 值 => 语法}。如果值为下划线,则代表了不满足以上所有情况下的默认情况如何处理。此外,match case中,主要一个case分支满足并处理了,就不会继续判断下一个case的分支了。(区别Java的break;)object Object {def main(args: Array[String]): Unit = {def judgeGeade(grade : String): Unit ={grade match {case "A" => println("A");case "B" => println("B");case "C" => println("C");case "D" => println("D");case _   => println("没有默认匹配的")}}judgeGeade("A");judgeGeade("E");}}b、模式匹配中使用if守卫:Scala的模式匹配语法,有一个特点在于,可以在case后的条件判断中,不仅仅只是提供一个值,而是可以在值的后面再加一个if守卫,进行双重过滤:        object Object {def main(args: Array[String]): Unit = {def judgeGeade(name : String ,grade : String): Unit ={grade match {case "A" => println(name + "A");case "B" => println(name +" B");case "C" => println(name +" C");case "D" => println(name +" D");case _ if name == "张三三" => println(name + ",you are luck boy!");case _   => println("没有默认匹配的")}}judgeGeade("张三三","A");}}c、在模式匹配中进行变量赋值:Scala的模式匹配语法中,有一个特点在于,可以将模式匹配的默认情况,下划线,替换为一个变量名,此时模式匹配语法就会将要匹配的值赋值给这个变量,从而可以在后面的处理语句中使用要匹配的值:优点:可以显示出_grade的值;object Object {def main(args: Array[String]): Unit = {def judgeGeade(name : String ,grade : String): Unit ={grade match {case "A" => println(name + "A");case "B" => println(name +" B");case "C" => println(name +" C");case "D" => println(name +" D");case _grade if name == "张三三" => println(name + ",you are luck boy!" + _grade);case _   => println("没有默认匹配的")}}judgeGeade("张三三","E");}}
4.2:对类型进行模式匹配:Scala的模式匹配一个强大之处就在于,可以直接匹配类型,而不是值。object Object {def main(args: Array[String]): Unit = {def processException(e : Exception): Unit ={e match {case e1 : IllegalArgumentException => println("IllegalArgumentException" + e1);case e2 : FileNotFoundException => println("FileNotFoundException" + e2);case e3 : IndexOutOfBoundsException => println("IndexOutOfBoundsException" + e3);case _ : Exception => println("Exception");}}processException(new IllegalArgumentException());}}
4.3:对Array和List的元素进行模式匹配:对Array进行模式匹配,分别可以匹配带有指定元素的数组,带有指定个数元素的数组,以某元素打头的数组。对List进行模式匹配,与Array类似,但是需要使用List特有的::操作符;object Object {def main(args: Array[String]): Unit = {def greeting(arr : Array[String]): Unit ={arr match {case Array("张三三") => println("hi,张三三");case Array(a,b,c,d) => println("hi," + a +" ,"+ b + ", " + c + " ,"+ d);case Array("李思思",_*) => println("hi,李思思");case _ => println("hi,how are you.")}}greeting(Array("张三三","李思思","王五五","a","b","c","d"));greeting(Array("李思思"));greeting(Array("a","b","c","d"));}}//使用List来进行模式匹配;object Object {def main(args: Array[String]): Unit = {def greeting(list : List[String]): Unit ={list match {case "张三三" :: Nil => println("hi,张三三");case a :: b :: c :: d => println("hi,"+ a +" ,"+ b + ", " + c + " ,"+ d);case "李思思" :: tail => println("hi,李思思");case _ => println("hi,how are you.")}}greeting(List("张三三"));greeting(List("李思思"));greeting(List("王五五"));}}
4.4:case class与模式匹配:Scala中提供了一种特殊的类,用case class进行声明,中文也可以称做样例类。case class其实有点类似于Java中的JavaBean的概念。即只定义field,并且由Scala编译时自动提供getter和setter方法,但是没有method。case calss的主构造函数接受的参数通常不需要使用var或者val修饰,scala自动就会使用val修饰,但是如果你自己使用var修饰,name还是会按照var来。Scala自动为case class定义了伴生对象,也就是Obeject,并且定义了apply()方法,该方法接受主构造函数中相同的参数,并且返回case class对象。    case class Student(name : String,classroom : String) extends Person{}case class Teacher(name : String,subject : String) extends  Person {}class Person{def judge(p : Person): Unit ={p match {case Teacher(name,subject) => println("teacher ,name is: "+ name +",subject is :" +subject)case Student(name,classroom) => println("student,name is: " + name +", classroot is :" + classroom);case _ => println("illegal access,please go out of the school")}}}//定义一个Objectobject Object {def main(args: Array[String]): Unit = {val zhangsan : Person = Teacher("张三三","语文");val lisisi : Person = Teacher("李思思","数学");val wangwu : Person = Student("王五五","一年级");val person = new Person;person.judge(zhangsan);person.judge(lisisi);person.judge(wangwu);}}4.5:Option与模式匹配:Scala有一种特殊的类型,叫做Option。Option有两种值,一种是Some,表示有值,一种是None,表示没有值。Option通常会用于模式匹配中,用于判断某个变量是有值还是没有值,这比null来的更加简明。class Person{val grades = Map("张三三" -> "A" ,"李思思" -> "B","王五五" -> "C");def getGrade(name :String): Unit ={val grade = grades.get(name);grade match {case Some(grade) => println("you grade is : " + grade);case None => println("sorry,you grade is null")}}}//定义一个Objectobject Object {def main(args: Array[String]): Unit = {val p = new Person;p.getGrade("张三三");p.getGrade("李思思");p.getGrade("王五五");p.getGrade("赵六六");}}

5:Scala中的类型参数:

其实就是类似于Java中的泛型。也是定义一种类型参数,比如在集合,在类,在函数中,定义类型参数,然后就可以保证使用到该类型参数的地方,就肯定,也只能是这种类型。从而实现程序更好的健壮性。

5.1:泛型类:顾名思义,其实就是在类的声明中,定义一些泛型类型,然后在类内部,比如field或者method,就可以使用这些泛型类型。使用泛型类,通常是需要对类中的某些成员,比如某些field或者method中的参数或者变量,进行统一的类型限制,这样可以保证程序更好的健壮性和稳定性。如果不使用泛型进行统一的类型限制,那么在后期程序运行过程中,难免出现问题,比如传入了不希望的类型,导致程序出现问题。在使用类的时候,比如创建类的对象,将类型参数替换为实际的类型,即可。或者直接给使用了泛型类型的field赋值时候,Scala会自动进行类型推断。class Person[T](val id : T){def getMessage(name : T) ={println("id:" + id + ",name:" + name);}}//定义一个Object进行测试object Object {def main(args: Array[String]): Unit = {val p = new Person[String]("1008611");p.getMessage("张三三");}}
5.2:泛型函数:泛型函数,与泛型类类似,可以给某个函数在声明的时候指定泛型类型,然后再函数体内,多个变量或者返回值之间,就可以使用泛型类型进行声明,从而对某个特殊的变量,或者多个变量,进行强制性的类型限制。于泛型类一样,你可以通过给使用了泛型类型的变量传递值来让Scala自动推断泛型的实际类型,也可以在调用函数时候,手动指定泛型类型。class Person{def getCard[T](content : T)={if(content.isInstanceOf[Int]){println("card:001:" + content );}else if(content.isInstanceOf[String]){println("card:002:" + content);}else{println("card:003:" + content)}}}//定义一个Object进行测试object Object {def main(args: Array[String]): Unit = {val p = new Person();p.getCard("张三三");p.getCard(24)p.getCard(true)}}
5.3:上边界Bounds:在指定泛型类型的时候,有时候,我们需要对泛型类型的范围进行界定,而不是可以是任意的。比如,我们可能要求某个泛型类型,它就必须是某个类的子类,这样在程序中就可以放心的调用泛型类型继承的父类的方法,程序才能正常的使用和运行。此时就可以使用上下边界Bounds的特性。Scala的上下边界特性允许泛型类型必须是某个类的子类,或者必须是某个类的父类。class Person(val name : String){def hello = println("hi.i am " + name);def makeFriends(p : Person): Unit ={hello;p.hello}}//定义一个Student继承Personclass Student(name : String) extends Person(name){}//定义一个类Party使用上边界class Party[T <: Person](p1 : T,p2 : T) {//def play = p1.makeFriends(p2);def play(): Unit ={p1.makeFriends(p2);}}//定义一个Object进行测试object Object {def main(args: Array[String]): Unit = {val s1 = new Student("张三三");val s2 = new Student("李思思");val p = new Party[Person](s1,s2);p.play()}}
5.4:下边界Bounds:除了指定泛型类型的上边界,还可以指定下边界,即指定泛型类型必须是某个类的父类;    class Father(val name : String) {

    }    class Child(name : String) extends Father(name){

    }    //定义一个Object进行测试    object Object {

      def getIdCard[R >: Child](person : R): Unit ={        if(person.getClass == classOf[Child]){          println("请告诉我你爸爸的姓名!")        }else if(person.getClass == classOf[Father]){          println("请拿走你孩子的身份证!")        }else{          println("你开心就好!")        }      }      def main(args: Array[String]): Unit = {        val c = new Child("张三三");        getIdCard(c);        val f = new Father("李思思");        getIdCard(f)      }    }
5.5:View Bounds:上下边界Bounds,虽然可以让一种泛型类型,支持有父子关系的多种类型。但是,在某个类与上下边界Bounds指定的父子类型范围内的类都没有任何关系,则默认是肯定不能接受的。然而,View Bounds作为一种上下边界Bounds的加强版,支持可以对类型进行隐式转换,将指定的类型进行隐式转换后,再判断是否在边界指定的类型范围内:    class Person(val name : String) {

    }    class Dog(val name : String) {

      def hello(): Unit ={        println("汪汪汪汪,i am " + name)      }    }    class Patty[T <% Person](p1 :T,p2 : T) {

      def show(): Unit ={        println("View Bounds的练习学习")      }    }        //定义一个Object进行测试    object Object {

      implicit def dog2Person(dog : Object) : Person ={        if(dog.isInstanceOf[Dog]){          val _dog = dog.asInstanceOf[Dog];          new Person(_dog.name);        }else{          null;        }      }

      def main(args: Array[String]): Unit = {        val person = new Person("张三三");        val dog = new Dog("小旺旺");

        val party = new Patty[Person](person,dog);        party.show()      }    }
5.6:Context Bounds:是一种特殊的Bounds,它会根据泛型类型的声明,比如"T : 类型"要求必须存在一个类型为"类型[T]"的隐式值。其实,Context Bounds之所以叫Context,是因为它基于的是一种全局的上下文,需要使用到上下文中的隐式值以及注入。
5.7:Manifest Context Bounds:在Scala中,如果要实例化一个泛型数组,就必须使用Manifest Context Bounds。也就是说,如果数组元素类型为T的话或者函数定义[T :Manifest]泛型类型,这样才能实例化Array[T]这种泛型数组;    class Meat(val name : String) {

    }    class Vegetable(val name : String) {

    }        //定义一个Object进行测试    object Object {

      def foodPackage[T : Manifest](food : T*) ={        val foodPackage = new Array[T](food.length);        for(i <- 0 until(food.length)){          foodPackage(i) = food(i);        }        foodPackage;      }      def main(args: Array[String]): Unit = {        val m1 = new Meat("大肉");        val v1 = new Vegetable("胡萝卜");

        println(foodPackage(m1,v1).toBuffer);      }    }
5.8:协变和逆变:Scala中的协变和逆变是非常有特色的,解决了Java中的泛型的一大缺憾。比如,Java中,如果有Professional是Master的子类,那么Card[Professional]是不是Card[Master]的子类呢,答案是,肯定不是啊。因此对于发开程序造成了很多的麻烦。而Scala中,只要灵活使用了协变和逆变,就可以解决Java中泛型的问题。    class Master {

    }    class Professional extends Master{

    }    class Card[+T](val name : String) {      //+是协变      def enterMeet(card : Card[Master]): Unit ={        println("欢迎大师以及大师级别以下的来到会场")      }    }    class Card2[-T](val name : String){

      def enterMeet2(card : Card2[Professional]): Unit ={        println("只有专家级别的才可以进入此会场,如果是大师级别的当然更可以了")      }    }    //定义一个Object进行测试    object Object {

      def main(args: Array[String]): Unit = {        val p = new Card[Professional]("张三三专家");        val m = new Card[Master]("李思思大师");        p.enterMeet(m);        m.enterMeet(p);

        val p2 = new Card2[Professional]("张三三专家");        val m2 = new Card2[Master]("李思思大师");        p2.enterMeet2(p2);        p2.enterMeet2(m2);        m2.enterMeet2(p2);        m2.enterMeet2(m2);      }    }
5.9:Existential Type:  在Scala里面,有一种特殊的类型参数,就是    Existential Type,即存在性类型。    Array[T] forSome{type T}    Array[_]

6:Scala之隐式转换与隐式参数:

  允许手动指定,将某种类型的对象转换成其他类型的对象。最核心的就是定义隐式转换函数,即implicit conversion function。定义的隐式转换函数,只要在编写的程序内引入,就会被Scala自动使用。Scala会根据隐式转换函数的签名,在程序中使用隐式转换函数接受的参数类型定义的对象时,会自动将其传入隐式转换函数,转换为另外一种类型的对象并且返回。这就是"隐式转换";隐式转换函数的名字随便起,因为通常不会由用户手动调用,而是Scala进行调用的。但是如果要使用隐式转换,则需要对隐式转换函数进行导入。因此通常建议将隐式转换函数的名称命名为"one2one"的形式。

6.1:隐式转换:实现隐式转换,只要在程序可见的范围内定义隐式转换函数即可。Scala会自动使用隐式转换函数。隐式转换函数与普通函数唯一的语法区别就是,要以implicit开头,而且一定要定义函数返回类型。class Student(val name : String) {}class Older(val name : String) {}class SpecialPerson(val name : String) {var ticketNum = 0;def buySpecialTicket(p : SpecialPerson): Unit ={ticketNum += 1;println("票数:" + ticketNum);}}//定义一个Object来测试object Object {implicit def object2SpecialPerson(obj : Object) : SpecialPerson = {if(obj.getClass == classOf[Student]){val s = obj.asInstanceOf[Student];new SpecialPerson(s.name);}else if(obj.getClass == classOf[Older]){val older = obj.asInstanceOf[Older];new SpecialPerson(older.name);}else{null;}}def main(args: Array[String]): Unit = {val s = new Student("张三三");val o = new Older("李思思");val specialPerson = new SpecialPerson("王五五");specialPerson.buySpecialTicket(s);specialPerson.buySpecialTicket(o);specialPerson.buySpecialTicket(specialPerson);}}
6.2:使用隐式转换加强现有类型:隐式转换非常强大的一个功能,就是可以在不知不觉中加强现有类型的功能。也就是说,可以为,某个类定义一个加强版的类,并定义互相之间的隐式转换,从而让源类在使用加强版的方法时,由Scala自动进行隐式转换为加强肋,然后再调用该方法。class Man(val name : String) {}class SuperMan(val name : String) {def emitLaser = println(name + " ,变身超人");}//定义一个Object来测试object Object {implicit def man2SuperMan(man : Man):SuperMan = new SuperMan(man.name);def main(args: Array[String]): Unit = {val man = new Man("张三三");man.emitLaser;}}
6.3:导入隐式转换函数(隐式转换函数作用域与导入):Scala默认会使用两种隐式转换,一种是源类型,或者目标类型的伴生对象内的隐式转换函数;一种是当前程序作用域内的可以用唯一标识标识的隐式转换函数。如果隐式转换函数不在上述两种情况下的话,那么就必须手动使用import语法引入某个包下的隐式转换函数,比如import test._。通常建议,仅仅在需要进行隐式转换的地方,比如某个函数或者非法内,用import导入隐式转换函数,这样可以缩小隐式转换函数的作用域,避免不需要的隐式转换。6.4:隐式转换的发生时机:a、调用某个函数,但是给函数传入的参数的类型,与函数定义的接受参数类型不匹配。b、使用某个类型的对象,调用某个方法,而这个方法并不存在与该类型中。c、使用某个类型的对象,调用某个方法,虽然该类型有这个方法,但是给方法传入的参数类型,与方法定义的接受参数的类型不匹配。
6.5:隐式参数:所谓的隐式参数,指的是在函数或者方法中,定义一个用implicit修饰的参数,此时Scala会尝试找到一个指定类型的,用implicit修饰的对象,即隐式值,并注入参数。Scala会在两个范围内查找,一种是当前作用域内可见的val或者var定义的隐式变量。一种是隐式参数类型的伴生对象内的隐式值。class SignPen {def write(context: String) = println(context);}object Object {implicit val signPen = new SignPen;def signForExam(name : String)(implicit  signPen : SignPen){signPen.write(name + " come to exam in time;")}def main(args: Array[String]): Unit = {signForExam("张三三");}}

7:Scala之Actor(多线程编程,注意,Spark中使用的分布式多线程框架,是Akka):

  Scala的Actor类似于Java中的多线程编程。但是不同的是,Scala的Actor提供的模型与多线程有所不同。Scala的Actor尽可能的避免锁和共享状态,从而避免多线程并发时出现资源争用的情况,进而提示多线程编程的性能。此外,Scala的Actor的这种模型还可以避免死锁等一系列传统多线程编程的问题。

7.1:Actor的创建,启动,和消息的收发:Scala提供了Actor trait来让我们更方便的进行Actor多线程编程,就Actor trait就类似于Java中的thread和Runnable一样,是基础的多线程基类和接口。我们只要重写Actor trait的act方法,即可实现自己的线程执行体,与Java中重写run方法类似。此外,使用start()方法启动actor,使用!符号,向actor发送消息。actor内部使用receive和模式匹配接受消息。class HelloActor extends Actor{def act(): Unit = {while(true) {receive{case name : String => println("hi," + name)}}}}//定义一个Object来进行测试object Object {def main(args: Array[String]): Unit = {val helloActor = new HelloActor;helloActor.start()}}
7.2:收发case class类型的消息:Scala的Actor模型和Java的多线程模型之间,很大的一个区别就是,Scala Actor天然支持线程之间的精确通信。即一个actor可以给其他actor直接发送消息。这个功能是非常强大和方便的。要给一个actor发送消息,需要使用"actor ! 消息"的语法。在Scala中,通常建议使用样例举,即case class来作为消息进行发送。然后在actor接受消息以后,可以使用scala强大的模式匹配功能来进行不同消息的处理。case class Login(name : String,passsword : String) {}case class register(name : String,password : String) {}class UserManageActor extends Actor{def act(): Unit = {while (true){receive{case Login(name,passsword) => println("name : " + name + ",password : " + passsword);case register(name,passsword) => println("name : " + name + ",password : " + passsword);}}}}//定义一个Object来进行测试object Object {def main(args: Array[String]): Unit = {val userManageActor = new UserManageActor;userManageActor.start();//userManageActor ! Register("张三三","123456");//userManageActor ! Login("张三三","123456");
      }}7.3:Actor之间互相收发消息:如果两个Actor之间要互相收发消息,那么Scala的建议是,一个actor向另一个actor发送消息时,同时带上自己的引用。其他actor收到自己的消息时,直接通过发送消息的actor的引用,即可以给它回复消息。7.4:同步消息和Future:默认情况下,消息都是异步的。但是如果希望发送的消息时同步的,即对方接受后,一定要给自己返回结果,name可以使用!?的方式发送消息。即val reply = actor !? message;如果要异步发送一个消息,但是在后续要获得消息的返回值,那么可以使用Future。即!!语法。val future = actor !! message。val reply = future();

待续......

转载于:https://www.cnblogs.com/biehongli/p/8426626.html

Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、...相关推荐

  1. Scala学习教程笔记二之函数式编程、Object对象、伴生对象、继承、Trait、

    1:Scala之函数式编程学习笔记: 1:Scala函数式编程学习:1.1:Scala定义一个简单的类,包含field以及方法,创建类的对象,并且调用其方法:class User {private v ...

  2. 2021年大数据常用语言Scala(二十七):函数式编程 聚合操作

    目录 聚合操作 聚合  reduce 定义 案例 折叠  fold 定义 案例 聚合操作 聚合操作,可以将一个列表中的数据合并为一个.这种操作经常用来统计分析中 聚合  reduce reduce表示 ...

  3. Scala入门到精通——第十八节 隐式转换与隐式参数(一)

    本节主要内容 隐式转换简介 隐式转换函数 隐式转换规则 隐式参数 1. 隐式转换简介 在Scala语言当中,隐式转换是一项强大的程序语言功能,它不仅能够简化程序设计,也能够使程序具有很强的灵活性.要想 ...

  4. scala之隐式转换

    目录 0.隐式转换定义 1.函数隐式转换 2.使用隐式转换加强现有类型 3.隐式转换函数的作用域与导入 4.隐式参数 5.隐式转换的发生时机 0.隐式转换定义 实现方式:隐式转换函数接收的参数类型定义 ...

  5. 深度学习入门教程UFLDL学习实验笔记三:主成分分析PCA与白化whitening

     深度学习入门教程UFLDL学习实验笔记三:主成分分析PCA与白化whitening 主成分分析与白化是在做深度学习训练时最常见的两种预处理的方法,主成分分析是一种我们用的很多的降维的一种手段,通 ...

  6. AI火爆干货最全整理!五套深度学习和算法学习教程和三套Python学习视频!!!限时无套路免费领取!...

    点击蓝色"AI专栏"关注我哟 选择"星标",重磅干货,第一时间送达 这是站长第 31 期免费送丰富宝贵的干货资源与教程 本期绝对是满满的干货! 获取更多资源请关 ...

  7. 阅读笔记–Java 8函数式编程,建议看书,作者高屋建瓴

    阅读笔记–Java 8函数式编程 书籍代码 为什么需要再次修改Java 1996年1月,Java1.0发布,商业发展需要更复杂的应用,跑在功能强大的多核CPU机器上.带有高效运行时编译器的Java虚拟 ...

  8. scala学习复习笔记超详细(变量)

    文章目录 Scala变量 1. 变量的快速入门 变量的使用说明: 程序中 + 的使用: 2. Scala数据类型 Scala 数据类型体系一览图 Scala数据类型列表 整数类型 浮点类型 字符类型 ...

  9. javascript深入浅出——学习笔记(六种数据类型和隐式转换)

    在慕课之前学过JS深入浅出,最近发现很多东西都记不太清楚了,再复习一遍好了,感觉这个课程真的超级棒的,做做笔记,再添加一些学习内容?随时补充 课程大纲 1.数据类型 2.表达式和运算符 3.语句 4. ...

  10. scala学习之旅(十三):隐式转换和隐式参数

    文章地址:http://www.haha174.top/admin/article/list 1.引言 scala 提供的隐式转换和隐式参数功能,是非常有特色的功能.是java 等编程语言所没有的功能 ...

最新文章

  1. ehcache导致Tomcat重启出错
  2. 设计模式所遵循的原则及模式之间的关系
  3. SIFT,SURF,ORB,FAST 特征提取算法比较
  4. 科大星云诗社动态20210830
  5. spark2.4.5源码编译成hadoop-2.6.0-cdh5.15.1
  6. django-重写登录认证(可以使用用户名或手机号登录)
  7. Oracle笔记-USRS01.DBF文件过大,解决办法
  8. 用筷子吃汉堡?汉堡王新广告被指种族歧视 网友:想成为下一个DG?
  9. index.php文件分析,OpenCart index.php分析
  10. 如何在 Mac 上给文件、文件夹和磁盘重新命名?
  11. Java(31)_JDBC连接mysql数据库(一)
  12. flacs 安装教程_绍兴拖拽式撬装加油装置建站方案
  13. 2020软考信息系统项目管理师-上午历年真题解析视频课程-任铄-专题视频课程
  14. 超级详细的IDEA设置Java类和方法的注释模板
  15. matlab 合成t检验,[zz]用MATLAB做T检验(ttest)
  16. 解决win10笔记本电脑Wifi频繁自动断开
  17. CODEVS 1069 关押罪犯
  18. 【线性代数】1.2矩阵的行列式与克莱姆法则
  19. Python通过fake_useragent实现生成随机UserAgent
  20. 算法语言Scheme修订6报告 R6RS简体中文翻译

热门文章

  1. Android 字母导航条实现
  2. 文件系统读写Linux文件系统损坏的修复技术Strut2教程-java教程
  3. html文件执行php语句
  4. 2012年,拥抱梦想实现梦想!
  5. 学习笔记_2011-10-02
  6. Android_(服务)Vibrator振动器
  7. netty权威指南学习笔记一——NIO入门(4)AIO
  8. 【JVM】上帝视角看JVM内存模型,分而治之论各模块详情
  9. ssm整合之配置applicationContext-service.xml
  10. 几种数据库快速csv入库方式整理