1. 程式人生 > >Scala 隱式轉換和隱式引數

Scala 隱式轉換和隱式引數

1.隱式轉換

    隱式轉換函式是以implicit關鍵字宣告的帶有單個引數的函式。這種函式將會自動應用,將值從一種型別轉換為另一種型別。

implicit def a(d: Double) = d.toInt

//不加上邊這句你試試

val i1: Int = 3.5

println(i1)

 

2.利用隱式轉換豐富類庫功能

    如果需要為一個類增加一個方法,可以通過隱式轉換來實現。比如想為File增加一個read方法,可以如下定義:

class RichFile(val from: File) {

  def read = Source.fromFile(from.getPath).mkString

}

 

implicit def file2RichFile(from: File) = new RichFile(from)

 

val contents = new File("C:\\Users\\61661\\Desktop\\scala筆記.txt").read

println(contents)

    有什麼好處呢?好處就是你可以不修改原版本的程式碼而為原本的程式碼增加新功能。

 

3.隱式值

    將name變數標記為implicit,所以編譯器會在方法省略隱式引數的情況下去搜索作用域內的隱式值作為缺少引數。

implicit val name = "Nick"

def person(implicit name: String) = name

println(person)

    但是如果此時你又相同作用域中定義一個隱式變數,再次呼叫方法時就會報錯:出現二義性

implicit val name = "Nick"

implicit val name2 = "Nick"

def person(implicit name: String) = name

println(person)

 

4. 隱式檢視

(1)隱式轉換為目標型別:把一種型別自動轉換到另一種型別

def foo(msg : String) = println(msg)

implicit def intToString(x : Int) = x.toString

foo(10)

(2)隱式轉換呼叫類中本不存在的方法

class Dog {

  val name = "金毛"

}

 

class Skill{

  def fly(animal: Dog, skill: String) = println(animal.name + "已領悟" + skill)

}

 

object Learn{

  implicit def learningType(s : Dog) = new Skill

}

 

object Main2 extends App{

  override def main(args: Array[String]): Unit = {

    import unit15.Learn._

    val dog = new Dog

    dog.fly(dog, "飛行技能")

  }

}

    當然了,以上操作也可以定義在包物件中,即,在object Learn的外面再套一層,package,沒問題的!

 

 

5.隱式類

    在scala2.10後提供了隱式類,可以使用implicit宣告類,但是需要注意以下幾點:

--  其所帶的構造引數有且只能有一個

--  隱式類必須被定義在“類”或“伴生物件”或“包物件”裡

--  隱式類不能是case class(case class在定義會自動生成伴生物件與2矛盾)

--  作用域內不能有與之相同名稱的標示符

object StringUtils {

  implicit class StringImprovement(val s : String){ //隱式類

    def increment = s.map(x => (x +1).toChar)

  }

}

object Main3 extends  App{

  import unit15.StringUtils._

  println("mobin".increment)

}

 

6.隱式的轉換時機

(1)當方法中的引數的型別與目標型別不一致時

(2)當物件呼叫所在類中不存在的方法或成員時,編譯器會自動將物件進行隱式轉換

 

 

7. 隱式解析機制

    即編譯器是如何查詢到缺失資訊的,解析具有以下兩種規則:

(1)首先會在當前程式碼作用域下查詢隱式實體(隱式方法、隱式類、隱式物件)。

(2)如果第一條規則查詢隱式實體失敗,會繼續在隱式引數的型別的作用域裡查詢。型別的作用域是指與該型別相關聯的全部伴生模組,一個隱式實體的型別T它的查詢範圍如下:

    a)  如果T被定義為T with A with B with C,那麼A,B,C都是T的部分,在T的隱式解析過程中,它們的伴生物件都會被搜尋。

    b)  如果T是引數化型別,那麼型別引數和與型別引數相關聯的部分都算作T的部分,比如List[String]的隱式搜尋會搜尋List的伴生物件和String的伴生物件。

    c)  如果T是一個單例型別p.T,即T是屬於某個p物件內,那麼這個p物件也會被搜尋。

    d)  如果T是個型別注入S#T,那麼S和T都會被搜尋。

 

 

8.隱式轉換的前提

(1)不能存在二義性

(2)隱式操作不能巢狀