1:Scala和Java的对比:

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

2:Scala之函数式编程:

  1. 2.1:将函数赋值给变量:
        Scala中的函数是一等公民,可以独立定义,独立存在,而且可以直接将函数作为值赋值给变量,必须在函数后面加上空格和下划线:
        class Person{
  2.  
  3.       def hello(name : String) = {
            println("hi," + name)
          }
          //将函数赋值给变量的语法,函数命令 _(1、函数名称,2、空格,3、下划线)
          val sayHello = hello _;
          sayHello("张三");
        }
        //定义一个Object来测试
        object Object {
  4.  
  5.       def main(args: Array[String]): Unit = {
            val p1 = new Person;
            p1.sayHello
          }
        }
    2.2:匿名函数:
        Scala中,函数也可以不需要命名,此时函数被称为匿名函数。可以直接定义函数之后,将函数赋值给某个变量,也可以将直接定义的匿名函数传入其他函数之中。Scala定义匿名函数的语法规则就是:(参数名称:参数类型) => 函数体;这种语法必须掌握和深刻理解。
        class Person{
  6.  
  7.       val sayHello = (name : String) => println("hi,"+ name);
        }
        //定义一个Object来测试
        object Object {
  8.  
  9.       def main(args: Array[String]): Unit = {
            val p1 = new Person;
            p1.sayHello("张三");
          }
        }
    2.3:高阶函数:
        Scala中,由于函数是一等公民,因此可以直接将某个函数传入其他函数,作为参数。这个功能是及其强大的,也是Java这种面向对象的编程语言所不具备的。
        接受其他函数作为参数的函数,也被称作为高阶函数(higher-order function),高阶函数的另一个功能就是将函数作为返回值:
        class Person{
  10.  
  11.       val sayHello = (name : String) => println("hi,"+ name);
          //def 函数名称(函数名称:(函数类型) => 函数返回值,参数1 :参数类型......)
          def greeting(hello:(String) => Unit, name: String): Unit ={
            hello(name);
          }
        }
        //定义一个Object来测试        
        object Object {
  12.  
  13.       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 {
  14.  
  15.       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{
  16.  
  17.       //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) ,"王五五");
  18.  
  19.       //如果仅有一个参数在右侧的函数体内只使用一次,则还可以将接受参数省略,并且将参数用_来替代。
          def triple(func:(Int) =>Int) ={
            func(3)
          }
  20.  
  21.     }
        //定义一个Object来测试
        object Object {
  22.  
  23.       def main(args: Array[String]): Unit = {
            val p1 = new Person;
            println(p1.triple(10 * _))
          }
        }
    2.5:Scala的常用的高阶函数:
        amap,对传入的每个元素都进行映射,返回一个处理后的元素:
            println(Array(1,2,3,4,5).map(2 * _).toBuffer);
        bforeach,对传入的每个元素都进行处理,但是没有返回值:
            (1 to 9).map("*" * _).foreach(println _);
        cfilter,对传入的每个元素都进行条件判断,如果对元素返回true,则保留该元素,否则过滤掉该元素:
            val a = (1 to 20).filter(_ % 2 ==0);
            println(a)
        dreduceLeft,从左侧元素开始,进行reduce操作,即先对元素1和元素2进行处理,然后将结果与元素3处理,再将结果与元素4处理,依次类推,即为reduce
            var a = (1 to 9).reduceLeft(_ * _);
            //此操作相当于1*2*3*4*5*6*7*8*9
            println(a)
        esortWith,对元素进行两两相比,进行排序:
            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{
  24.  
  25.           def getGreetingFunc(msg : String) = (name : String) => println(msg + "," + name);
              //两次调用getGreetingFunc函数,传入不同的msg,并创建不同的函数返回.
              //然而,msg只是一个局部变量,却在getGreetingFunc执行完以后,还可以继承存在创建的函数之中。
              //greetingFuncHello("张三"),调用的时候,值为"hello"的msg被保留在了函数体内部,可以反复的使用。
              //这种变量超出了其作用域,还可以使用的情况,即为闭包。
  26.  
  27.           val greetingFuncHello = getGreetingFunc("hello");
              val greetingFuncHi = getGreetingFunc("hi");
              //Scala通过为每个函数创建对象来实现闭包,实际上对于getGreetingFunc函数创建的函数。msg是作为函数对象的变量存在的。因此每个函数才可以拥有不同的msg
              //Scala编译器会确保上述闭包机制。
  28.  
  29.         }
            //定义一个Object来测试
            object Object {
  30.  
  31.           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{
  32.  
  33.       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 {
  34.  
  35.       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{
  36.  
  37.       def greeting(name : String) ={
            def hello(name : String): String ={
               return "hello," + name;
            }
            hello(name);
          }
        }        
        //定义一个Object来测试    
        object Object {
  38.  
  39.       def main(args: Array[String]): Unit = {
            val p = new Person;
            println(p.greeting("李思思"));
          }
        }

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

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

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

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

  1. 4.1:模式匹配的基础语法:
  2. amathch case的语法如下所示:变量 mathch {case => 语法}。如果值为下划线,则代表了不满足以上所有情况下的默认情况如何处理。此外,match case中,主要一个case分支满足并处理了,就不会继续判断下一个case的分支了。(区别Javabreak;)
  3. object Object {
  4.  
  5. def main(args: Array[String]): Unit = {
  6. def judgeGeade(grade : String): Unit ={
  7. grade match {
  8. case "A" => println("A");
  9. case "B" => println("B");
  10. case "C" => println("C");
  11. case "D" => println("D");
  12. case _ => println("没有默认匹配的")
  13. }
  14. }
  15. judgeGeade("A");
  16. judgeGeade("E");
  17. }
  18. }
  19. b、模式匹配中使用if守卫:
  20. Scala的模式匹配语法,有一个特点在于,可以在case后的条件判断中,不仅仅只是提供一个值,而是可以在值的后面再加一个if守卫,进行双重过滤:
  21. object Object {
  22.  
  23. def main(args: Array[String]): Unit = {
  24. def judgeGeade(name : String ,grade : String): Unit ={
  25. grade match {
  26. case "A" => println(name + "A");
  27. case "B" => println(name +" B");
  28. case "C" => println(name +" C");
  29. case "D" => println(name +" D");
  30. case _ if name == "张三三" => println(name + ",you are luck boy!");
  31. case _ => println("没有默认匹配的")
  32. }
  33. }
  34. judgeGeade("张三三","A");
  35. }
  36. }
  37. c、在模式匹配中进行变量赋值:
  38. Scala的模式匹配语法中,有一个特点在于,可以将模式匹配的默认情况,下划线,替换为一个变量名,此时模式匹配语法就会将要匹配的值赋值给这个变量,从而可以在后面的处理语句中使用要匹配的值:
  39. 优点:可以显示出_grade的值;
  40. object Object {
  41.  
  42. def main(args: Array[String]): Unit = {
  43. def judgeGeade(name : String ,grade : String): Unit ={
  44. grade match {
  45. case "A" => println(name + "A");
  46. case "B" => println(name +" B");
  47. case "C" => println(name +" C");
  48. case "D" => println(name +" D");
  49. case _grade if name == "张三三" => println(name + ",you are luck boy!" + _grade);
  50. case _ => println("没有默认匹配的")
  51. }
  52. }
  53. judgeGeade("张三三","E");
  54. }
  55. }
  56. 4.2:对类型进行模式匹配:
  57. Scala的模式匹配一个强大之处就在于,可以直接匹配类型,而不是值。
  58. object Object {
  59.  
  60. def main(args: Array[String]): Unit = {
  61. def processException(e : Exception): Unit ={
  62. e match {
  63. case e1 : IllegalArgumentException => println("IllegalArgumentException" + e1);
  64. case e2 : FileNotFoundException => println("FileNotFoundException" + e2);
  65. case e3 : IndexOutOfBoundsException => println("IndexOutOfBoundsException" + e3);
  66. case _ : Exception => println("Exception");
  67. }
  68. }
  69. processException(new IllegalArgumentException());
  70. }
  71. }
  72. 4.3:对ArrayList的元素进行模式匹配:
  73. Array进行模式匹配,分别可以匹配带有指定元素的数组,带有指定个数元素的数组,以某元素打头的数组。
  74. List进行模式匹配,与Array类似,但是需要使用List特有的::操作符;
  75. object Object {
  76.  
  77. def main(args: Array[String]): Unit = {
  78. def greeting(arr : Array[String]): Unit ={
  79. arr match {
  80. case Array("张三三") => println("hi,张三三");
  81. case Array(a,b,c,d) => println("hi," + a +" ,"+ b + ", " + c + " ,"+ d);
  82. case Array("李思思",_*) => println("hi,李思思");
  83. case _ => println("hi,how are you.")
  84. }
  85. }
  86. greeting(Array("张三三","李思思","王五五","a","b","c","d"));
  87. greeting(Array("李思思"));
  88. greeting(Array("a","b","c","d"));
  89. }
  90. }
  91. //使用List来进行模式匹配;
  92. object Object {
  93.  
  94. def main(args: Array[String]): Unit = {
  95. def greeting(list : List[String]): Unit ={
  96. list match {
  97. case "张三三" :: Nil => println("hi,张三三");
  98. case a :: b :: c :: d => println("hi,"+ a +" ,"+ b + ", " + c + " ,"+ d);
  99. case "李思思" :: tail => println("hi,李思思");
  100. case _ => println("hi,how are you.")
  101. }
  102. }
  103. greeting(List("张三三"));
  104. greeting(List("李思思"));
  105. greeting(List("王五五"));
  106.  
  107. }
  108. }
  109. 4.4:case class与模式匹配:
  110. Scala中提供了一种特殊的类,用case class进行声明,中文也可以称做样例类。case class其实有点类似于Java中的JavaBean的概念。即只定义field,并且由Scala编译时自动提供gettersetter方法,但是没有methodcase calss的主构造函数接受的参数通常不需要使用var或者val修饰,scala自动就会使用val修饰,但是如果你自己使用var修饰,name还是会按照var来。Scala自动为case class定义了伴生对象,也就是Obeject,并且定义了apply()方法,该方法接受主构造函数中相同的参数,并且返回case class对象。
  111. case class Student(name : String,classroom : String) extends Person{
  112.  
  113. }
  114. case class Teacher(name : String,subject : String) extends Person {
  115.  
  116. }
  117. class Person{
  118.  
  119. def judge(p : Person): Unit ={
  120. p match {
  121. case Teacher(name,subject) => println("teacher ,name is: "+ name +",subject is :" +subject)
  122. case Student(name,classroom) => println("student,name is: " + name +", classroot is :" + classroom);
  123. case _ => println("illegal access,please go out of the school")
  124. }
  125. }
  126. }
  127. //定义一个Object
  128. object Object {
  129.  
  130. def main(args: Array[String]): Unit = {
  131. val zhangsan : Person = Teacher("张三三","语文");
  132. val lisisi : Person = Teacher("李思思","数学");
  133.  
  134. val wangwu : Person = Student("王五五","一年级");
  135. val person = new Person;
  136. person.judge(zhangsan);
  137. person.judge(lisisi);
  138. person.judge(wangwu);
  139. }
  140. }
  141.  
  142. 4.5:Option与模式匹配:
  143. Scala有一种特殊的类型,叫做OptionOption有两种值,一种是Some,表示有值,一种是None,表示没有值。Option通常会用于模式匹配中,用于判断某个变量是有值还是没有值,这比null来的更加简明。
  144. class Person{
  145.  
  146. val grades = Map("张三三" -> "A" ,"李思思" -> "B","王五五" -> "C");
  147. def getGrade(name :String): Unit ={
  148. val grade = grades.get(name);
  149. grade match {
  150. case Some(grade) => println("you grade is : " + grade);
  151. case None => println("sorry,you grade is null")
  152. }
  153. }
  154. }
  155. //定义一个Object
  156. object Object {
  157.  
  158. def main(args: Array[String]): Unit = {
  159. val p = new Person;
  160. p.getGrade("张三三");
  161. p.getGrade("李思思");
  162. p.getGrade("王五五");
  163. p.getGrade("赵六六");
  164. }
  165. }

5:Scala中的类型参数:

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

  1. 5.1:泛型类:
  2. 顾名思义,其实就是在类的声明中,定义一些泛型类型,然后在类内部,比如field或者method,就可以使用这些泛型类型。使用泛型类,通常是需要对类中的某些成员,比如某些field或者method中的参数或者变量,进行统一的类型限制,这样可以保证程序更好的健壮性和稳定性。如果不使用泛型进行统一的类型限制,那么在后期程序运行过程中,难免出现问题,比如传入了不希望的类型,导致程序出现问题。在使用类的时候,比如创建类的对象,将类型参数替换为实际的类型,即可。或者直接给使用了泛型类型的field赋值时候,Scala会自动进行类型推断。
  3. class Person[T](val id : T){
  4.  
  5. def getMessage(name : T) ={
  6. println("id:" + id + ",name:" + name);
  7. }
  8. }
  9. //定义一个Object进行测试
  10. object Object {
  11.  
  12. def main(args: Array[String]): Unit = {
  13. val p = new Person[String]("");
  14. p.getMessage("张三三");
  15. }
  16. }
  17. 5.2:泛型函数:
  18. 泛型函数,与泛型类类似,可以给某个函数在声明的时候指定泛型类型,然后再函数体内,多个变量或者返回值之间,就可以使用泛型类型进行声明,从而对某个特殊的变量,或者多个变量,进行强制性的类型限制。于泛型类一样,你可以通过给使用了泛型类型的变量传递值来让Scala自动推断泛型的实际类型,也可以在调用函数时候,手动指定泛型类型。
  19. class Person{
  20.  
  21. def getCard[T](content : T)={
  22. if(content.isInstanceOf[Int]){
  23. println("card:001:" + content );
  24. }else if(content.isInstanceOf[String]){
  25. println("card:002:" + content);
  26. }else{
  27. println("card:003:" + content)
  28. }
  29. }
  30. }
  31. //定义一个Object进行测试
  32. object Object {
  33.  
  34. def main(args: Array[String]): Unit = {
  35. val p = new Person();
  36. p.getCard("张三三");
  37. p.getCard()
  38. p.getCard(true)
  39. }
  40. }
  41. 5.3:上边界Bounds:
  42. 在指定泛型类型的时候,有时候,我们需要对泛型类型的范围进行界定,而不是可以是任意的。比如,我们可能要求某个泛型类型,它就必须是某个类的子类,这样在程序中就可以放心的调用泛型类型继承的父类的方法,程序才能正常的使用和运行。此时就可以使用上下边界Bounds的特性。Scala的上下边界特性允许泛型类型必须是某个类的子类,或者必须是某个类的父类。
  43. class Person(val name : String){
  44.  
  45. def hello = println("hi.i am " + name);
  46. def makeFriends(p : Person): Unit ={
  47. hello;
  48. p.hello
  49. }
  50. }
  51. //定义一个Student继承Person
  52. class Student(name : String) extends Person(name){
  53.  
  54. }
  55. //定义一个类Party使用上边界
  56. class Party[T <: Person](p1 : T,p2 : T) {
  57.  
  58. //def play = p1.makeFriends(p2);
  59. def play(): Unit ={
  60. p1.makeFriends(p2);
  61. }
  62. }
  63. //定义一个Object进行测试
  64. object Object {
  65.  
  66. def main(args: Array[String]): Unit = {
  67. val s1 = new Student("张三三");
  68. val s2 = new Student("李思思");
  69.  
  70. val p = new Party[Person](s1,s2);
  71. p.play()
  72. }
  73. }
  74. 5.4:下边界Bounds:
  75. 除了指定泛型类型的上边界,还可以指定下边界,即指定泛型类型必须是某个类的父类;
        class Father(val name : String) {
  76.  
  77.     }
        class Child(name : String) extends Father(name){
  78.  
  79.     }
        //定义一个Object进行测试
        object Object {
  80.  
  81.       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)
          }
        }
  82. 5.5:View Bounds:
  83. 上下边界Bounds,虽然可以让一种泛型类型,支持有父子关系的多种类型。但是,在某个类与上下边界Bounds指定的父子类型范围内的类都没有任何关系,则默认是肯定不能接受的。然而,View Bounds作为一种上下边界Bounds的加强版,支持可以对类型进行隐式转换,将指定的类型进行隐式转换后,再判断是否在边界指定的类型范围内:
        class Person(val name : String) {
  84.  
  85.     }
        class Dog(val name : String) {
  86.  
  87.       def hello(): Unit ={
            println("汪汪汪汪,i am " + name)
          }
        }
        class Patty[T <% Person](p1 :T,p2 : T) {
  88.  
  89.       def show(): Unit ={
            println("View Bounds的练习学习")
          }
        }    
        //定义一个Object进行测试
        object Object {
  90.  
  91.       implicit def dog2Person(dog : Object) : Person ={
            if(dog.isInstanceOf[Dog]){
              val _dog = dog.asInstanceOf[Dog];
              new Person(_dog.name);
            }else{
              null;
            }
          }
  92.  
  93.       def main(args: Array[String]): Unit = {
            val person = new Person("张三三");
            val dog = new Dog("小旺旺");
  94.  
  95.         val party = new Patty[Person](person,dog);
            party.show()
          }
        }
  96. 5.6:Context Bounds:
  97. 是一种特殊的Bounds,它会根据泛型类型的声明,比如"T : 类型"要求必须存在一个类型为"类型[T]"的隐式值。其实,Context Bounds之所以叫Context,是因为它基于的是一种全局的上下文,需要使用到上下文中的隐式值以及注入。
       
  98. 5.7:Manifest Context Bounds:
  99. Scala中,如果要实例化一个泛型数组,就必须使用Manifest Context Bounds。也就是说,如果数组元素类型为T的话或者函数定义[T :Manifest]泛型类型,这样才能实例化Array[T]这种泛型数组;
        class Meat(val name : String) {
  100.  
  101.     }
        class Vegetable(val name : String) {
  102.  
  103.     }    
        //定义一个Object进行测试
        object Object {
  104.  
  105.       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("胡萝卜");
  106.  
  107.         println(foodPackage(m1,v1).toBuffer);
          }
        }
  108. 5.8:协变和逆变:
  109. Scala中的协变和逆变是非常有特色的,解决了Java中的泛型的一大缺憾。比如,Java中,如果有ProfessionalMaster的子类,那么Card[Professional]是不是Card[Master]的子类呢,答案是,肯定不是啊。因此对于发开程序造成了很多的麻烦。而Scala中,只要灵活使用了协变和逆变,就可以解决Java中泛型的问题。
        class Master {
  110.  
  111.     }
        class Professional extends Master{
  112.  
  113.     }
        class Card[+T](val name : String) {
          //+是协变
          def enterMeet(card : Card[Master]): Unit ={
            println("欢迎大师以及大师级别以下的来到会场")
          }
        }
        class Card2[-T](val name : String){
  114.  
  115.       def enterMeet2(card : Card2[Professional]): Unit ={
            println("只有专家级别的才可以进入此会场,如果是大师级别的当然更可以了")
          }
        }
        //定义一个Object进行测试
        object Object {
  116.  
  117.       def main(args: Array[String]): Unit = {
            val p = new Card[Professional]("张三三专家");
            val m = new Card[Master]("李思思大师");
            p.enterMeet(m);
            m.enterMeet(p);
  118.  
  119.         val p2 = new Card2[Professional]("张三三专家");
            val m2 = new Card2[Master]("李思思大师");
            p2.enterMeet2(p2);
            p2.enterMeet2(m2);
            m2.enterMeet2(p2);
            m2.enterMeet2(m2);
          }
        }
  120. 5.9:Existential Type:
      Scala里面,有一种特殊的类型参数,就是    Existential Type,即存在性类型。
        Array[T] forSome{type T}
        Array[_]

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

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

  1. 6.1:隐式转换:
  2. 实现隐式转换,只要在程序可见的范围内定义隐式转换函数即可。Scala会自动使用隐式转换函数。隐式转换函数与普通函数唯一的语法区别就是,要以implicit开头,而且一定要定义函数返回类型。
  3. class Student(val name : String) {
  4.  
  5. }
  6. class Older(val name : String) {
  7.  
  8. }
  9. class SpecialPerson(val name : String) {
  10.  
  11. var ticketNum = ;
  12. def buySpecialTicket(p : SpecialPerson): Unit ={
  13. ticketNum += ;
  14. println("票数:" + ticketNum);
  15. }
  16. }
  17. //定义一个Object来测试
  18. object Object {
  19.  
  20. implicit def object2SpecialPerson(obj : Object) : SpecialPerson = {
  21. if(obj.getClass == classOf[Student]){
  22. val s = obj.asInstanceOf[Student];
  23. new SpecialPerson(s.name);
  24. }else if(obj.getClass == classOf[Older]){
  25. val older = obj.asInstanceOf[Older];
  26. new SpecialPerson(older.name);
  27. }else{
  28. null;
  29. }
  30. }
  31.  
  32. def main(args: Array[String]): Unit = {
  33. val s = new Student("张三三");
  34. val o = new Older("李思思");
  35. val specialPerson = new SpecialPerson("王五五");
  36.  
  37. specialPerson.buySpecialTicket(s);
  38. specialPerson.buySpecialTicket(o);
  39. specialPerson.buySpecialTicket(specialPerson);
  40. }
  41. }
  42. 6.2:使用隐式转换加强现有类型:
  43. 隐式转换非常强大的一个功能,就是可以在不知不觉中加强现有类型的功能。也就是说,可以为,某个类定义一个加强版的类,并定义互相之间的隐式转换,从而让源类在使用加强版的方法时,由Scala自动进行隐式转换为加强肋,然后再调用该方法。
  44. class Man(val name : String) {
  45.  
  46. }
  47. class SuperMan(val name : String) {
  48.  
  49. def emitLaser = println(name + " ,变身超人");
  50. }
  51. //定义一个Object来测试
  52. object Object {
  53.  
  54. implicit def man2SuperMan(man : Man):SuperMan = new SuperMan(man.name);
  55.  
  56. def main(args: Array[String]): Unit = {
  57. val man = new Man("张三三");
  58. man.emitLaser;
  59. }
  60. }
  61. 6.3:导入隐式转换函数(隐式转换函数作用域与导入):
  62. Scala默认会使用两种隐式转换,一种是源类型,或者目标类型的伴生对象内的隐式转换函数;一种是当前程序作用域内的可以用唯一标识标识的隐式转换函数。如果隐式转换函数不在上述两种情况下的话,那么就必须手动使用import语法引入某个包下的隐式转换函数,比如import test._。通常建议,仅仅在需要进行隐式转换的地方,比如某个函数或者非法内,用import导入隐式转换函数,这样可以缩小隐式转换函数的作用域,避免不需要的隐式转换。
  63.  
  64. 6.4:隐式转换的发生时机:
  65. a、调用某个函数,但是给函数传入的参数的类型,与函数定义的接受参数类型不匹配。
  66. b、使用某个类型的对象,调用某个方法,而这个方法并不存在与该类型中。
  67. c、使用某个类型的对象,调用某个方法,虽然该类型有这个方法,但是给方法传入的参数类型,与方法定义的接受参数的类型不匹配。
  68. 6.5:隐式参数:
  69. 所谓的隐式参数,指的是在函数或者方法中,定义一个用implicit修饰的参数,此时Scala会尝试找到一个指定类型的,用implicit修饰的对象,即隐式值,并注入参数。Scala会在两个范围内查找,一种是当前作用域内可见的val或者var定义的隐式变量。一种是隐式参数类型的伴生对象内的隐式值。
  70. class SignPen {
  71.  
  72. def write(context: String) = println(context);
  73. }
  74. object Object {
  75.  
  76. implicit val signPen = new SignPen;
  77.  
  78. def signForExam(name : String)(implicit signPen : SignPen){
  79. signPen.write(name + " come to exam in time;")
  80. }
  81. def main(args: Array[String]): Unit = {
  82. signForExam("张三三");
  83. }
  84. }

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

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

  1. 7.1:Actor的创建,启动,和消息的收发:
  2. Scala提供了Actor trait来让我们更方便的进行Actor多线程编程,就Actor trait就类似于Java中的threadRunnable一样,是基础的多线程基类和接口。我们只要重写Actor traitact方法,即可实现自己的线程执行体,与Java中重写run方法类似。
  3. 此外,使用start()方法启动actor,使用!符号,向actor发送消息。actor内部使用receive和模式匹配接受消息。
  4. class HelloActor extends Actor{
  5.  
  6. def act(): Unit = {
  7. while(true) {
  8. receive{
  9. case name : String => println("hi," + name)
  10. }
  11. }
  12. }
  13. }
  14. //定义一个Object来进行测试
  15. object Object {
  16.  
  17. def main(args: Array[String]): Unit = {
  18. val helloActor = new HelloActor;
  19. helloActor.start()
  20. }
  21. }
  22. 7.2:收发case class类型的消息:
  23. ScalaActor模型和Java的多线程模型之间,很大的一个区别就是,Scala Actor天然支持线程之间的精确通信。即一个actor可以给其他actor直接发送消息。这个功能是非常强大和方便的。要给一个actor发送消息,需要使用"actor ! 消息"的语法。在Scala中,通常建议使用样例举,即case class来作为消息进行发送。然后在actor接受消息以后,可以使用scala强大的模式匹配功能来进行不同消息的处理。
  24. case class Login(name : String,passsword : String) {
  25.  
  26. }
  27. case class register(name : String,password : String) {
  28.  
  29. }
  30. class UserManageActor extends Actor{
  31.  
  32. def act(): Unit = {
  33. while (true){
  34. receive{
  35. case Login(name,passsword) => println("name : " + name + ",password : " + passsword);
  36. case register(name,passsword) => println("name : " + name + ",password : " + passsword);
  37. }
  38. }
  39. }
  40. }
  41. //定义一个Object来进行测试
  42. object Object {
  43.  
  44. def main(args: Array[String]): Unit = {
  45. val userManageActor = new UserManageActor;
  46. userManageActor.start();
  47. //userManageActor ! Register("张三三","123456");
  48. //userManageActor ! Login("张三三","123456");
  49. }
  50. }
  51.  
  52. 7.3:Actor之间互相收发消息:
  53. 如果两个Actor之间要互相收发消息,那么Scala的建议是,一个actor向另一个actor发送消息时,同时带上自己的引用。其他actor收到自己的消息时,直接通过发送消息的actor的引用,即可以给它回复消息。
  54.  
  55. 7.4:同步消息和Future:
  56. 默认情况下,消息都是异步的。但是如果希望发送的消息时同步的,即对方接受后,一定要给自己返回结果,name可以使用!?的方式发送消息。即val reply = actor !? message;如果要异步发送一个消息,但是在后续要获得消息的返回值,那么可以使用Future。即!!语法。val future = actor !! messageval reply = future();

待续......

Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、的更多相关文章

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

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

  2. 9、scala函数式编程-集合操作

    一.集合操作1 1.Scala的集合体系结构 // Scala中的集合体系主要包括:Iterable.Seq.Set.Map.其中Iterable是所有集合trait的根trai.这个结构与Java的 ...

  3. Scala学习教程笔记一之基础语法,条件控制,循环控制,函数,数组,集合

    前言:Scala的安装教程:http://www.cnblogs.com/biehongli/p/8065679.html 1:Scala之基础语法学习笔记: :声明val变量:可以使用val来声明变 ...

  4. python笔记三:函数式编程

    1.概念: 函数式编程就是一种抽象程度很http://i.cnblogs.com/EditPosts.aspx?opt=1高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要 ...

  5. Scala入门系列(十二):隐式转换

    引言 Scala提供的隐式转换和隐式参数功能,是非常有特色的功能.是Java等编程语言所没有的功能.它可以允许你手动指定,将某种类型的对象转换成其他类型的对象.通过这些功能可以实现非常强大而且特殊的功 ...

  6. Scala 中的隐式转换和隐式参数

    隐式定义是指编译器为了修正类型错误而允许插入到程序中的定义. 举例: 正常情况下"120"/12显然会报错,因为 String 类并没有实现 / 这个方法,我们无法去决定 Stri ...

  7. Objective-C 基础教程第三章,面向对象编程基础知

    目录 Objective-C 基础教程第三章,面向对象编程基础知 0x00 前言 0x01 间接(indirection) 0x02 面向对象编程中使用间接 面向过程编程 面向对象编程 0x03 OC ...

  8. Scala学习系列(三)——入门与基础

    本课程源码共享于 https://github.com/tree1123/learning-scala 首先,打开IDEA编辑器的SbtExampleProject项目,我们将在这个项目下进行练习 本 ...

  9. 大数据学习day17------第三阶段-----scala05------1.Akka RPC通信案例改造和部署在多台机器上 2. 柯里化方法 3. 隐式转换 4 scala的泛型

    1.Akka RPC通信案例改造和部署在多台机器上  1.1 Akka RPC通信案例的改造(主要是把一些参数不写是) Master package com._51doit.akka.rpc impo ...

随机推荐

  1. 【ARTS】01_20_左耳听风-20190325~20190331

    zz## ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 ...

  2. Linux嗅探ettercap

    场景 拿到一台C段的Linux服务器,对目标主机进行嗅探 ettercap安装 操作环境 Centos 6 $ sudo yum install -y libtool-ltdl ncurses-dev ...

  3. pt-table-checksum 使用方法【转】

    27. pt-table-checksum27.1 pt-table-checksum 作用 主要用来检查主从数据是否一致,原理即在主库执行把表每行的列通过concat函数进行拼接,然后对拼接的值进行 ...

  4. python父类调用子类了解一下

    class B(): def __init__(self): pass def start(self): print(self.parse()) class A(B): def __init__(se ...

  5. requests库入门08-delete请求

    还是使用GitHub的接口,之前我们新增了邮箱,这次使用delete请求来删除邮箱,接口文档地址 import requests test_url = 'https://api.github.com' ...

  6. wtforms-表单生成及验证

    介绍 wtforms是一个支持多个web框架的form组件,主要用来做表单的验证以及生成的, 安装 pip install wtforms 使用 自定义一个类,继承wtforms.Form类,定义字段 ...

  7. 题解-SDOI2015 约数个数和

    Problem bzoj3994 洛谷3327 题意:设 \(d(x)\) 为 \(x\) 的约数个数,给定 \(N,M\),求\(\sum_{i=1}^N\sum_{j=1}^Md(ij)\) \( ...

  8. django-form介绍

    Django form表单   目录 普通方式手写注册功能 views.py login.html 使用form组件实现注册功能 views.py login2.html 常用字段与插件 initia ...

  9. 45)django-分页实现

    Django提供了一个新的类来帮助你管理分页数据,.它可以接收列表.元组或其它可迭代的对象. 一:常用方法 >>> from django.core.paginator import ...

  10. 彻底搞懂字符集编码:ASCII,Unicode 和 UTF-8

    一.ASCII 码 我们知道,计算机内部,所有信息最终都是一个二进制值.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte).也就是说,一个 ...