天天看點

Scala高階函數與隐式轉換

Scala 官網:http://www.scala-lang.org/

一、高階函數

1、函數化簡
package com.example.scala

/**
 * Created by Bruce on 2017/6/12.
 */
/**
 * ⑴接收其他函數作為參數的函數,被稱作高階函數(higher-order function);
 * ⑵Scala中,由于函數是一等公民,是以可以直接将某個函數傳入其他函數,作為參數;
 * ⑶高階函數的另外一個功能是将函數作為傳回值;
 * ⑷高階函數可以自動推斷出函數類型,而不需要寫明類型;而且對于隻有一個參數的函數,還可以省去其小括号;
 * 如果僅有的一個參數在右側的函數體内隻使用一次,則還可以将接收參數省略,用_來替代即可;
 * Array(2,3,5,6).map((x:Int)=>{x*3})
 * Array(2,3,5,6).map((x)=>{x*3})
 * Array(2,3,5,6).map((x)=>x*3)
 * Array(2,3,5,6).map(x=>x*3)
 * Array(2,3,5,6).map(_*3)
 */
object functionN extends App{
  def myTest(x: Int, y: Int) = {
    x * y + 20
  }

  def fun1(f: (Int, Int) => Int, a: Int, b: Int) = {
    f(a, b)
  }
  println(fun1(myTest, 100, 5))
}
           
Scala高階函數與隐式轉換
2、常見的高階函數
Scala高階函數與隐式轉換

二、隐式轉換

1、隐式轉換

⑴Scala提供的隐式轉換和隐式參數功能,是非常有特色的功能,是Java等程式設計語言所沒有的功能。它可以允許手動指定将某種類型的對象轉換成其他類型的對象。

⑵Scala的隐式轉換,其實最核心的就是定義隐式轉換函數,即implicit conversion function。定義的隐式轉換函數,隻要在編寫的程式内引入,就會被Scala自動使用。Scala會根據隐式轉換函數的簽名,在程式中使用到隐式轉換函數接收的參數類型定義的對象時,會自動将其傳入隐式轉換函數,轉換為另外一種類型的對象并傳回。這就是隐式轉換。

⑶隐式轉換函數叫什麼名字是無所謂的,通常不會由使用者手動調用,而是由Scala進行調用。然而,如果要手動使用隐式轉換,則需要對隐式轉換函數進行導入。是以通常将隐式轉換函數的名稱命名為“one2one”的形式。

⑷要實作隐式轉換,隻要在程式可見的範圍内定義隐式轉換函數即可。Scala會自動使用隐式轉換函數。隐式轉換函數與普通函數唯一的文法差別就是,要以implicit開頭,而且要指定函數傳回類型。

package com.example.scala

/**
 * Created by Bruce on 2017/6/12.
 */
class SpecialPerson(val name: String)
class Student1(val name: String)
class Older(val name: String)

object Implicit extends App{
  var ticketNm = 0

  def buySpecialTticket(spe: SpecialPerson) = {
    ticketNm += 1
    spe.name + "'s ticket number is " + ticketNm
  }

  implicit def object2SpecialPerson(obj: Object):SpecialPerson = {
    //隐式轉換函數需要使用implict聲明
    //隐式轉換的函數名稱習慣為:被轉換類型2目标類型
    //隐式轉換函數需要顯性的定義傳回類型
    println("************************")
    if (obj.getClass == classOf[Student1]) {
      val stu = obj.asInstanceOf[Student1]
      new SpecialPerson(stu.name)
    }
    else if (obj.getClass == classOf[Older]) {
      val old = obj.asInstanceOf[Older]
      new SpecialPerson(old.name)
    }
    else new SpecialPerson("None")
  }
  println(buySpecialTticket(new Student1("bruce")))
}
           
Scala高階函數與隐式轉換

2、隐式轉換-加強類

⑴隐式轉換強大之處就是可以在不知不覺中加強現有類型的功能。也就是說,可以為某個類定義一個加強版的類,并定義互相之間的隐式轉換,進而讓源類在使用加強版的方法時,由Scala自動進行隐式轉換調用。

package com.example.scala

/**
 * Created by Bruce on 2017/6/12.
 */
/**
 * 隐式轉換強大之處就是可以在不知不覺中加強現有類型的功能。
 * 也就是說,可以為某個類定義一個加強版的類,并定義互相之間的隐式轉換,
 * 進而讓源類在使用加強版的方法時,由Scala自動進行隐式轉換為加強類,然後在調用該方法;
 * @param name
 */
class Man(val name: String)

class SuperMan(val name: String) {
  def emitLaser() = println("emiting laser......................")
}

object SuperMan extends App {

  val bruce=new Man("bruce")
  implicit def man2superman(man:Man):SuperMan={
    new SuperMan(man.name)
  }
  bruce.emitLaser()
}
           
Scala高階函數與隐式轉換
3、隐式轉換作用域與發生時機
package com.example.scala

/**
 * Created by Bruce on 2017/6/12.
 */
/**
 * ⑴Scala預設會使用兩種隐式轉換:
 * 一種是源類型,或者目标類型的伴生對象内的隐式轉換函數;
 * 一種是目前程式作用域内的可以用唯一辨別符表示的隐式轉換函數;
 * ⑵如果隐式轉換函數不在上述兩種情況下的話,那麼就需要手動使用import文法引入某個包下的隐式轉換函數,
 * 通常情況下,僅僅在需要進行隐式轉換的地方,比如某個函數或者方法内,用import導入隐式轉換函數,
 * 這樣可以縮小隐式轉換函數的作用域,避免不必要的隐式轉換;
 * ⑶發生時機
 * ①調用某個函數,但是給函數傳入的參數的類型,與函數定義的接收參數類型不比對;
 * ②使用某個類型的對象,調用某個方法,而這個方法并不存在于該類型時;
 * ③使用某個類型的對象,調用某個方法,雖然該類型有這個方法,但是給方法傳入的參數類型,與方法定義的接收參數的烈性不比對;
 * @param name
 */
class Man2(val name: String)

object SuperMan2{
  implicit def man22superman2(man:Man):SuperMan2={
    new SuperMan2(man.name)
  }
}

class SuperMan2(val name: String) {
  def emitLaser() = println("emiting laser......................")
}

object Implicit extends App {
  import com.example.scala.SuperMan2.man22superman2
  val bruce=new Man("bruce")
  bruce.emitLaser()
}
           
Scala高階函數與隐式轉換

4、隐式參數

⑴所謂的隐式參數,指的是在函數或者方法中,定義一個用implicit修飾的參數,此時Scala會嘗試找到一個指定類型的,用implicit修飾的對象,即隐式值,并注入參數。

⑵Scala會在兩個範圍内查找:一種是目前作用域内可見的val或者var定義的隐式變量;一種是隐式參數類型的伴生對象内的隐式值。

package com.example.scala

/**
 * Created by Bruce on 2017/6/12.
 */
/**
 * ⑴所謂的隐式參數,指的是在函數或者方法中,定義一個用implicit修飾的參數,此時Scala會嘗試找到一個指定類型的,用implicit修飾的對象,即隐式值,并注入參數。
 * ⑵Scala會在兩個範圍内查找:一種是目前作用域内可見的val或者var定義的隐式變量;一種是隐式參數類型的伴生對象内的隐式值。
 */
object implicitParse extends App{
  def test(implicit value:String) =println("the value is "+value)
  test("Scala")

  implicit val name="bruce"
  test
}
           
Scala高階函數與隐式轉換