1. 程式人生 > >Scala程式語言學習總結

Scala程式語言學習總結

                           Scala學習總結

一、Scala的簡介

      Scala是一種基於JVM的程式語言,學習目的主要是為了Spark的學習與相關程式碼的編寫。
    Scala的六大特徵:

        1).Java和scala可以無縫混編,都是執行在JVM上的
	2).型別推測(自動推測型別),不用指定型別  
	3).併發和分散式(Actor,類似Java多執行緒Thread) 
	4).特質trait,特徵(類似java中interfaces 和 abstract結合)
	5).模式匹配,match case(類似java switch case)
	6).高階函式(函式的引數是函式,函式的返回是函式),可進行函數語言程式設計

二、Scala安裝使用

  1. windows安裝,配置環境變數
  • 下載好後安裝。雙擊msi包安裝,記住安裝的路徑。

  • 配置環境變數(和配置jdk一樣)
             ①新建SCALA_HOME,配置好Scala安裝的目錄位置資訊。
             ②編輯Path變數,在後面追加如下:
               ;%SCALA_HOME%\bin;%SCALA_HOME%\jre\bin

  • 開啟cmd,輸入:scala - version 看是否顯示版本號,確定是否安裝成功
    在這裡插入圖片描述

  1. Scala程式編譯工具
        ①Scala ide
         下載網址:http://scala-ide.org/download/sdk.html

        ②推薦使用IDEA中配置scala外掛
         1》 開啟idea專案後,點選Configure->Plugins
    在這裡插入圖片描述     2》搜尋scala,點選Install安裝
    在這裡插入圖片描述     3》設定jdk,開啟Project Structure,點選new 選擇安裝好的jdk路徑
    在這裡插入圖片描述在這裡插入圖片描述     4》建立scala專案,配置scala sdk(Software Development Kit)
    在這裡插入圖片描述

三、Scala基礎

1.資料型別
在這裡插入圖片描述在這裡插入圖片描述在這裡插入圖片描述
2.變數和常量的宣告
    Scala中通常用var宣告變數,可修改;用val宣告常量,不可修改即不可對常量進行再賦值;不用指定資料型別,由Scala自己進行型別推測。
注意點:

在scala中每行後面不需要加分號,直接通過換行如來區分;但是一行中寫了多個語句,語句與語句之間必須用分號來分割
例如:

var age = 18   ; var name = "angelababy"
    
    var heighat,score = 10
    val sex = "male"

3.類和物件

class :修飾的稱為伴生類;定義在class中的屬性都是動態的,用於例項化 的;scala中的class類預設可以傳引數,預設的傳引數就是預設的建構函式。class 類屬性自帶getter ,setter方法。使用class時要new (必須new,除非在物件伴生用apply方法【在載入類的時候預設自動呼叫】已實經例化好),並且new的時候,class中除了方法不執行,其他都執行。

object: 修飾的稱為伴生物件;定義在object中的屬性(欄位、方法)都是靜 態的,main函式寫在裡面;scala 中的object是單例物件,相當於java中的工具類,可以看成是定義靜態的方法的類.object不可以傳引數。使用object時,不用new.

建立類

class Person{
  val name = "zhangsan"
  val age = 18
  def sayName() = {
    "my name is "+ name
  }
}

    在建立類時,可以在類名後面加入一個括號,括號中寫定義的引數型別,括號中的引數就表示類的建構函式由括號內的引數組成。補充: ①當引數用var修飾那麼可以通過物件修改其值;當引數用val修飾那麼無法通過物件來修改值;當引數沒有修飾符,那麼在外部無法通過物件來呼叫。
      ②若想增加一個類的傳入引數,則需要在宣告的類中重寫建構函式,這樣就可以在mian函式中宣告有增加的屬性的物件,當然原來的物件也可以宣告。
               重寫this函式

  /*
   *  重寫的建構函式,引數不能有修飾符
   */
  def this (id:Int,name:String,facePower:Double ){
    //首先要呼叫父建構函式
    this(id,name)
    fcp = facePower
    
  }

建立物件

object Lesson_Class {
   def main(args: Array[String]): Unit = {
    val person = new Person()
    println(person.age);
    println(person.sayName())
  }
}

Apply方法
       使用此方法時,可以在main函式中不通過new來建立一個物件,即可以不用專門的一次一次地進行例項化,載入建立物件的這個類的時候,會自動呼叫apply這個方法,類似Java中的static靜態塊。
       Apply方法的使用用例:

object ScalaDemo01 {
  def main(args: Array[String]): Unit = {
    val p = new Person("zs",19)
     val person = Person("wagnwu",10)   //不用使用new來建立一個例項
  }
}

class Person(xname :String , xage :Int){
  val name = "zs"
  val age = xage
  var gender = "m"
  def this(name:String,age:Int,g:String){
    this(name,age)
    gender = g
  }
}

object Person{
  def apply(name:String,age:Int)={
    new Person(name,age)  
  }
}

4.if{…}else{…}語句

    /**
     * if else 
     */
    val age =18 
    if (age < 18 ){
    	println("no allow")
    }else if (18<=age&&age<=20){
    	println("allow with other")
    }else{
    	println("allow self")
    }

5.for ,while,do…while
    ①to和until 的用法(不帶步長,帶步長區別)

 /**
     * to和until
     * 例:
     * 1 to 10 返回1到10的Range陣列,包含10
     * 1 until 10 返回1到10 Range陣列 ,不包含10
     */
    
    println(1 to 10 )//列印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
    
    println(1 to (10 ,2))//步長為2,從1開始列印 ,1,3,5,7,9
    
    println(1 until 10 ) //不包含最後一個數,列印 1,2,3,4,5,6,7,8,9
    
    println(1 until (10 ,3 ))//步長為2,從1開始列印,列印1,4,7

    ②for迴圈(可加判斷條件)

    //可以分號隔開,寫入多個list賦值的變數,構成多層for迴圈
    //scala中 不能寫count++ count-- 只能寫count+
    //可以在for迴圈中加入條件判斷
    var count = 0;
    for(i <- 1 to 10; j <- 1 until 10;if (i%2) == 0){
      println("i="+ i +",j="+j)
      count += 1
    }
    println(count);
    
    //例子: 列印小九九
    for(i <- 1 until 10 ;j <- 1 until 10){
      if(i>=j){
    	  print(i +" * " + j + " = "+ i*j+"	")  
      }
      if(i==j ){
        println()
      }
    }

補充: for迴圈用yield 關鍵字返回一個集合

/*
 *  yield 關鍵字
 *  1-100集合中的偶數儲存到另一個集合
 *  yield關鍵字能夠將符合要求的元素自動封裝到一個集合中
 */
val rest = for(i <- 1 to 100; if i%2 == 0) yield i     //此時rest就為選擇出的i構成的一個集合
for(elem <- rest) println(elem)

    ③while迴圈,while(){},do {}while()

   /**
     * while 迴圈
     */
    var index = 0 
    while(index < 100 ){
    	println("第"+index+"次while 迴圈")
      index += 1 
    }
    index = 0 
    do{
    	index +=1 
    	println("第"+index+"次do while 迴圈")
}while(index <100 )

6.函式
    ①普通函式

def fun (a: Int , b: Int ) : Unit = {
   println(a+b)
 }
fun(1,1)
    
def fun1 (a : Int , b : Int)= a+b
    println(fun1(1,2))  

    ②遞迴函式

 /**
     * 遞迴函式 
     * 5的階乘
     */
    def fun2(num :Int) :Int= {  //必須寫返回值型別
      if(num ==1)
        num
      else 
        num * fun2(num-1)
    }
    print(fun2(5))

    ③包含引數預設值的函式

 /**
   * 包含引數預設值的函式
   * 	1.	函式的引數有預設值,在調函式的時候可以傳參,也可以不傳參,
   * 	2.	若不傳參使用的預設值,
   * 	3.	如果傳參,預設值會被覆蓋
   */
  def fun2(num1:Int = 10,num2:Int = 20) = {
    num1 + num2
  }
  
  def fun3(num1:Int,num2:Int = 20) = {
    num1 + num2
  }
  
  def fun4(num1:Int=10,num2:Int) = {
    num1 + num2
  }
  呼叫:
   println(fun2())
   println(fun3(100))
   println(fun4(num2=1000))

    ④可變引數個數的函式:函式引數可以是一個也可以是多個,隨機靈活的

 def fun5(args:Double*) = {
    /**
     * 在scala中
     * 		+=前後的數值型別必須一致
     * 		+前後的數值型別可以不一致
     */
    var sum = 0.0
    for(arg <- args) sum += arg
    sum
  }

    ⑤匿名函式:沒有函式名的函式

/**
 * 匿名函式
 * 1.有引數匿名函式
 * 2.無引數匿名函式
 * 3.有返回值的匿名函式
 * 注意:
 * 可以將匿名函式返回給定義的一個變數
 * 匿名函式不能顯式宣告函式的返回型別

 */
//有引數匿名函式
val value1 = (a : Int) => {
  println(a)
}
value1(1)
//無引數匿名函式
val value2 = ()=>{
  println("我愛Angelababy")
}
value2()
//有返回值的匿名函式
val value3 = (a:Int,b:Int) =>{
  a+b
}
println(value3(4,4)) 

    ⑥巢狀函式

    /**
     * 巢狀函式:
     * 		在函式體內有定義了一個函式
     */
    def fun7(num:Int)={
      def fun8(a:Int,b:Int):Int={
        if(a == 1){
          b
        }else{
          fun8(a-1,a*b)
        }
      }
      fun8(num,1)
    }

    ⑦偏應用函式:偏應用函式是一種表示式,不需要提供函式需要的所有引數,只需要提供部分,或不提供所需引數。在多個函式呼叫時,有共同的引數被使用,則可提取出來預設寫死,只需要為函式提供部分的引數。

/**
 * 偏應用函式
 */
def log(date :Date, s :String)= {
  println("date is "+ date +",log is "+ s)
}

val date = new Date()
log(date ,"log1")
log(date ,"log2")
log(date ,"log3")

//想要呼叫log,以上變化的是第二個引數,可以用偏應用函式處理
val logWithDate = log(date,_:String)    //下劃線相當於佔位符的作用,手動傳入即可
logWithDate("log11")
logWithDate("log22")
logWithDate("log33")

    ⑧ 高階函式:函式的引數是函式,或者函式的返回型別是函式,或者函式的引數和函式的返回型別是函式的函式。

 //函式的引數是函式
    def hightFun(f : (Int,Int) =>Int, a:Int ) : Int = {
      f(a,100)
    }
    def f(v1 :Int,v2: Int):Int  = {
      v1+v2
    }
    
    println(hightFun(f, 1))
    
    //函式的返回是函式
    //1,2,3,4相加
    def hightFun2(a : Int,b:Int) : (Int,Int)=>Int = {
      def f2 (v1: Int,v2:Int) :Int = {
        v1+v2+a+b
      }
      f2
    }
    println(hightFun2(1,2)(3,4))
    
    //函式的引數是函式,函式的返回是函式
    def hightFun3(f : (Int ,Int) => Int) : (Int,Int) => Int = {
      f
    } 
    println(hightFun3(f)(100,200))
    println(hightFun3((a,b) =>{a+b})(200,200))
    //以上這句話還可以寫成這樣
    //如果函式的引數在方法體中只使用了一次 那麼可以寫成_表示
    println(hightFun3(_+_)(200,200))

    ⑨柯里化函式

    /**
       * 柯里化函式
       * 		可以理解為高階函式的簡化
       * 		klhFun函式就是對巢狀函式這種情況的高階函式的簡化版
       */

      def klhFun(a:Int)(b:Int) = a*b
      具體:
      def klhAllFun(a:Int):(Int)=>Int = {
        val fun = (b:Int)=>a*b
        fun
      }

7.Scala字串

val str1 = "hello bi"
    val str2 = "hello sh"
    val flag = str1.equalsIgnoreCase(str2)    
    println(flag)
    
    str1.split(" ")

    val strBuilder = new StringBuilder
    strBuilder.append("hello\t")
    strBuilder.append("bj")
    println(strBuilder)
    println("hello Angelababy".hashCode())

string操作方法舉例
1.比較:equals
2.比較忽略大小寫:equalsIgnoreCase
3.indexOf:如果字串中有傳入的assci碼對應的值,返回下標

  /**
     * String && StringBuilder
     */
    val str = "abcd"
    val str1 = "ABCD"
    
    println(str.indexOf(97))
    println(str.indexOf("b"))

    println(str==str1)
    /**
     * compareToIgnoreCase
     * 
     * 如果引數字串等於此字串,則返回值 0;
     * 如果此字串小於字串引數,則返回一個小於 0 的值;
     * 如果此字串大於字串引數,則返回一個大於 0 的值。
     * 
     */
    println(str.compareToIgnoreCase(str1))
    
    val strBuilder = new StringBuilder
    strBuilder.append("abc")
//    strBuilder.+('d')
    strBuilder+ 'd'
//    strBuilder.++=("efg")
    strBuilder++= "efg" 
//    strBuilder.+=('h')
    strBuilder+= 'h' 
    strBuilder.append(1.0)
    strBuilder.append(18f)
    println(strBuilder)

8.陣列

 //陣列  new String[10]
    /**
     * Array關鍵詞 建立一個長度為10 的Int型別的陣列
     * 如果建立了一個Int型別的陣列,那麼初始值都是0
     * String型別的陣列,初始是null
     * Boolean型別的陣列,初始是false
     */
    val nums = new Array[Int](10)
    for(index <- 0 until nums.length){
      nums(index) = index * index
    }
    nums.foreach {println }
    
    //二維陣列
    val secArray = new Array[Array[String]](10)
    for(index <- 0 until secArray.length){
      secArray(index) = new Array[String](10)
    }
    
    //往二維陣列中填充資料    
   /* for(i <- 0 until secArray.length){
      for(j <- 0 until secArray(i).length){
        secArray(i)(j) = i*j + ""
      }
    }*/
    for(i <- 0 until secArray.length;j <- 0 until secArray(i).length){
      secArray(i)(j) = i*j + ""
    }

9.List集合

   /**
    * list集合
    * 
    * list集合是一個不可變的集合
    * 可變的list集合
    */
    println("=========List==========")
    val list = List(1,2,3,4,5)
    list.contains(6)
    val dropList = list.drop(2)
    dropList.foreach { println }
    list.reverse
    list.take(3).foreach(println)
    val mapList1 = list.map { x=> x +"" }
    mapList1.foreach { x=>println(x) }
    println(list.exists { x => x > 300 })
    println(list.mkString("\t"))
    
    val logList = List("hello bj","hello sh")
    val mapList = logList.map { _.split(" ") }
//    mapList.foreach { x => x.foreach { println } }
    //flatMap方法   flat扁平 
    val flatMapList = logList.flatMap{_.split(" ")}
    flatMapList.foreach { println }

/**
     * 不可變的list集合
     * 建立list集合的方式:
     * 		1、List(1,2,3)
     * 		2、Nil關鍵建立  Nil:空List
     * 				::往集合中新增元素
     */
    val list = 2::1::Nil
    
    /**
     * 可變的list集合
     */
    val listBuffer = new ListBuffer[String]
    listBuffer.+=("hello")
    listBuffer.+=("bj")
    listBuffer.foreach { println }
    
    listBuffer.-=("hello")

10.set集合

   //建立 
    val set1 = Set(1,2,3,4,4)
    val set2 = Set(1,2,5)
    //遍歷
    //注意:set會自動去重
    set1.foreach { println}
   for(s <- set1){
      println(s)
    }
    println("*******")
   /**
    * 方法舉例
    */
    
   //交集
   val set3 = set1.intersect(set2)
   set3.foreach{println}
   val set4 = set1.&(set2)
   set4.foreach{println}
   println("*******")
   //差集
   set1.diff(set2).foreach { println }
   set1.&~(set2).foreach { println }
   //子集
   set1.subsetOf(set2)
   
   //最大值
   println(set1.max)
   //最小值
   println(set1.min)
   println("****")
   
   //轉成陣列,list
   set1.toArray.foreach{println}
   println("****")
   set1.toList.foreach{println}
   
   //mkString
   println(set1.mkString)
   println(set1.mkString("\t"))

11.Map集合

 val map = Map(
                  "1" -> "bj",
                  2 -> "sh",
                  3 -> "gz"
                )
    val keys = map.keys
    val keyIterator = keys.iterator
    while(keyIterator.hasNext){
      val key = keyIterator.next()
      /**
       * map集合的get方法返回值是一個Option型別的物件
       * Option型別有兩個子型別  分別為some None
       */
       Map中的方法 :
       1.	filter:過濾,留下符合條件的記錄
       2.	count:統計符合條件的記錄數
       3.	contains:map中是否包含某個key
       4.	exist:符合條件的記錄存在不存在

      println(key + "\t" + map.get(key).get)
    }
     
     /**
      * getOrElse 原理:
      * 		去集合中去取資料,若不存在返回預設值
      */
     println(map.get(4).getOrElse("default"))
    
     for(k <- map)
       println(k._1 + "\t" + k._2)     //分別取第一個位置的資料和第二個位置的資料,即Key-Value
       
     map.foreach(x=>println(x._1 + "\t" + x._2))    
     
     
     map.filter(x=>{
       Integer.parseInt(x._1 + "") >= 2
     }).foreach(println)
     
     val count = map.count(x=>{
       Integer.parseInt(x._1 + "") >= 2
     })
     println(count)
     
     /**
     合併Map的操作:
     1.++  例:map1.++(map2)  --map1中加入map2
     2.++:  例:map1.++:(map2) –map2中加入map1
     注意:合併map會將map中的相同key的value替換
     **/

12.元組

 /**
      * 元組 vs list
      * list建立的時候指定了泛型,那麼集合中必須是這個泛型的物件
      * 元祖中可以包含任意型別的元素,這些元素使用一對小括號來封裝,Tuple關鍵字
      * 
      * 
      */
     val t2 = Tuple2(1,"hello")
     val tt2 = (1,"hello")
     
     val t3 = Tuple3(1,true,"hello")  //可以存放Int、boolean、String多種不同的型別
     val tt3 = (1,true,"hello")
     
     val moreTuple = (1,2,3)   
     
      val tupleIterator = tt3.productIterator    //元組的遍歷
      while(tupleIterator.hasNext){
      println(tupleIterator.next())
    }
     //toString方法
     println(tt3.toString())
     //swap交換    注意只有二元組物件才會有這個方法
     val swapt2 = tt2.swap
     println(swapt2._1 + "\t" + swapt2._2)

13.Trait特性
       ①Trait的概念理解
1》 Scala Trait(特徵) 相當於 Java 的介面,實際上它比介面還功能強大。
2》與介面不同的是,它還可以定義屬性和方法的實現。抽象類和介面的結合。
3》一般情況下Scala的類可以繼承多個Trait,從結果來看就是實現了多重繼承。Trait的繼承用exten關鍵字繼承,多繼承時多個Trait之間用with連線。
4》Trait(特徵) 定義的方式與類類似,但它使用的關鍵字是 trait。
5》繼承的多個trait中如果有同名的方法和屬性,必須要在類中使用“override”重新定義。
6》trait中不可以傳引數

trait Read {
  val readType = "Read"
  val gender = "m"
  def read(name:String){
	println(name+" is reading")
  }
}

trait Listen {
  val listenType = "Listen"
  val gender = "m"
  def listen(name:String){
	println(name + " is listenning")
  }
}

class Person() extends Read with Listen{
  override val gender = "f"
}

object test {
  def main(args: Array[String]): Unit = {
    val person = new Person()
    person.read("zhangsan")
    person.listen("lisi")
    println(person.listenType)
    println(person.readType)
    println(person.gender)
    
  }
}

14.模式匹配Match…Case…
      ①概念理解
=>Java中的模式匹配為 switch case ;
=>Scala 提供了強大的模式匹配機制,應用也非常廣泛,除了匹配值還可以匹配型別,型別的匹配必須要有變數名
=>一個模式匹配包含了一系列備選項,每個都開始於關鍵字 case。
=>每個備選項都包含了一個模式及一到多個表示式。箭頭符號 => 隔開了模式和表示式。

object Lesson_Match {
  def main(args: Array[String]): Unit = {
    val tuple = Tuple6(1,2,3f,4,"abc",55d)
    val tupleIterator = tuple.productIterator
    while(tupleIterator.hasNext){
      matchTest(tupleIterator.next())
    }
    
  }
  /**
   * 注意點:
   * 1.模式匹配不僅可以匹配值,還可以匹配型別
   * 2.模式匹配中,從上到下順序匹配,如果匹配到對應的型別或值,就不再繼續往下匹配
   * 3.模式匹配中,都匹配不上時,會匹配到 case _ ,相當於default
   * 4. 模式匹配的時候,模式範圍小的在最前面
   */
  def matchTest(x:Any) ={
    x match {
      case x:Int=> println("type is Int")    //型別匹配,必須要有變數名
      case 1 => println("result is 1")
      case 2 => println("result is 2")
      case 3=> println("result is 3")
      case 4 => println("result is 4")
      case x:String => println("type is String")
//      case x :Double => println("type is Double")
      case _ => println("no match")
    }
  }
}

15.樣例類(case class)
     ①概念理解
       使用了case關鍵字的類定義就是樣例類(case classes),樣例類是種特殊的類。實現了類構造引數的getter方法(構造引數預設被宣告為val),當構造引數是宣告為var型別的,它將幫你實現setter和getter方法。
       樣例類預設幫你實現了toString,equals,copy和hashCode等方法。
       樣例類可以new, 也可以不用new

/**
      * 樣例類
      * 使用case 來修飾的類就叫樣例類
      * 
      * 樣例類和普通類有什麼區別?
      * 樣例類預設幫你實現了toString,equals,copy和hashCode等方法。
			樣例類可以new, 也可以不用new 
      */
     val s1 = Student(1,1)
     val s2 = Student(2,2)
     val s3 = Student(3,3)
     val s4 = Student(4,4)
     val s5 = Student(5,5)
     
     val sl = List(s1,s2,s3,s4,s5)
     //樣例類+match case
     sl.foreach { x => x match {
       case Student(1,1) => println("1 1")    //值匹配,且使用了樣例類已經寫好了的toString方法。
       case s:Student => println("Student" + s)    //型別匹配
       case _ => println("_______")
     } }
  } 
}
//樣例類
case class Student(val id :Int ,val age :Int)

16.Actor Model
     ①概念理解
         Actor Model是用來編寫平行計算或分散式系統的高層次抽象(類似java中的Thread)讓程式設計師不必為多執行緒模式下共享鎖而煩惱,被用在Erlang 語言上, 高可用性99.9999999 % 一年只有31ms 宕機Actors將狀態和行為封裝在一個輕量的程序/執行緒中,但是不和其他Actors分享狀態,每個Actors有自己的世界觀,當需要和其他Actors互動時,通過傳送事件和訊息,傳送是非同步的,非堵塞的(fire-andforget),傳送訊息後不必等另外Actors回覆,也不必暫停,每個Actors有自己的訊息佇列,進來的訊息按先來後到排列,這就有很好的併發策略和可伸縮性,可以建立效能很好的事件驅動系統。

Actor的特徵:
1.ActorModel是訊息傳遞模型,基本特徵就是訊息傳遞
2.訊息傳送是非同步的,非阻塞的
3.訊息一旦傳送成功,不能修改,類似於郵件的傳送來往
4.Actor之間傳遞時,自己決定決定去檢查訊息,而不是一直等待,是非同步非阻塞的

//Actor與Actor之間通訊
case class Message(actor:Actor,msg:Any)

class Actor1 extends Actor{
  def act(){
    while(true){
      receive{
        case  msg :Message => {      //型別匹配
          println("i sava msg! = "+ msg.msg)
          
          msg.actor!"i love you too !"
          }
        case msg :String => println(msg)
        case  _ => println("default msg!")
      }
    }
  }
}

class Actor2(actor :Actor) extends Actor{
  actor ! Message(this,"i love you !")
	def act(){
		while(true){
			receive{
  			case msg :String => {
  			  if(msg.equals("i love you too !")){
  			    println(msg)
  			   actor! "could we have a date !"
  			  }
  			}
  			case  _ => println("default msg!")
			}
		}
	}
}

object Lesson_Actor2 {
  def main(args: Array[String]): Unit = {
    val actor1 = new Actor1()
    actor1.start()
    val actor2 = new Actor2(actor1)
    actor2.start()
  }
}

17.Scala的隱式轉換系統
        隱式轉換,在編寫程式的時候可以儘量少的去編寫程式碼,讓編譯器去嘗試在編譯期間自動推匯出這些資訊來,這種特性可以極大的減少程式碼量,提高程式碼質量.
    ①隱式值+隱式檢視
通過implicit進行隱式的宣告

  object Scala09 {
  def main(args: Array[String]): Unit = {
//隱式值:
//  implicit var abc = "Dilireba"
    implicit var cba = "Angelababy"
    sayName   //直接呼叫,不用傳參 
  /* 將變數宣告為implicit,編譯器在執行sayName方法時發現缺少一個String型別的引數,
      此時會搜尋作用域內型別為String的隱式值
      並且將搜尋到的隱式值作為sayName的引數值
   */

    
    //    1.隱式轉換必須滿足無歧義規則
    //    2.宣告隱式引數的型別最好是自定義的資料型別,
    //    3.不要使用Int,String這些常用型別,防止碰巧衝突
    //    4.一般要將自定義的物件設定為隱式的
    
    //  隱式檢視  --》隱式轉換為目標型別:把一種型別自動轉換到另一種型別
    implicit def string2Int(num:String) = Integer.parseInt(num) 
	
    //addNum引數是tring,不符合要求,那麼他在編譯的時候,發現作用域內
    //    有一個隱式方法,正好這個方法的引數是String 返回值是Int  此時
    //呼叫隱式方法,返回一個Int值,在將Int傳給addNum
	
    println(addNum("1000"))
 
  }
  
  
  def addNum(num:Int) = {
      num + 1000
    }
  
  def sayName(implicit name:String) = {
    println("I Love " + name)
  }
  
}

    ②隱式類

   注意點:
    1.其所帶的構造引數有且只能有一個
    2.隱式類必須被定義在類,伴生物件和包物件裡
    3.隱式類不能是case class(case class在定義會自動生成伴生物件與2矛盾)
    4.作用域內不能有與之相同名稱的標示符
    
package com.hpe.scala

object Scala10 {
  def main(args: Array[String]): Unit = {
    //  隱式類   導包要從包名開始
    import com.hpe.scala.Util._     //Util下的所有類
    "abc".getLength()
    /**
     * "abc"這個字串想要呼叫getLength,但是自己沒有實現這個方法
     * 發現作用域內有一個隱式轉換的類,類的建構函式的引數是String型別
     * 自己傳給建構函式,得到這個類的物件,近而呼叫getLength方法
     */
  }
}

object Util{
  implicit class Int2String(s:String){
    def getLength() = s.length
  }
}

補充點:“_”在scala中的意義

  1. _表示所有 、2.佔位符、3.簡寫模式