Scala學習之路 (八)Scala的隱式轉換和隱式參數


一、概念

Scala 2.10引入了一種叫做隱式類的新特性。隱式類指的是用implicit關鍵字修飾的類。在對應的作用域內,帶有這個關鍵字的類的主構造函數可用於隱式轉換。

隱式轉換和隱式參數是Scala中兩個非常強大的功能,利用隱式轉換和隱式參數,你可以提供優雅的類庫,對類庫的使用者隱匿掉那些枯燥乏味的細節。 

二、作用

隱式的對類的方法進行增強,豐富現有類庫的功能

三、隱式參數

1)關鍵字:implicat
2)隱士的東西只能在object里面才能使用
3)作用域

四、隱式轉換函數

是指那種以implicit關鍵字聲明的帶有單個參數的函數。

可以通過::implicit –v這個命令顯示所有做隱式轉換的類。

四、隱士轉換的發生的時機

1、當一個對象去調用某個方法,但是這個對象並不具備這個方法

(1)scala源碼示例

1是Int類型,從to方法看,Int應該有to方法

打開Int類的源碼查看,並沒有Int本身並沒有to方法,發現Int繼承了AnyVal類

查看AnyVal類,發現AnyVal類同樣沒有to方法,而AnyVal類繼承了Any類

Any類里面沒有to方法,而在RichInt里面有to方法

而在上面查看scala自動導入隱式轉換函數時可以看到有Predef類的intWrapper方法,傳入的參數是Int,返回的結果類型是RichInt

(2)快學Scala示例值File和RichFile示例

不使用隱式轉換時,使用裝飾模式進行讀取

import java.io.File

import scala.io.Source

class RichFile(val file : File) {
  //定義一個read方法,返回String類型
  def read():String = Source.fromFile(file.getPath).mkString
}

object RichFile{
  //隱式轉換方法(將原有的File類型轉成了file類型,在用的時候需要導入相應的包)
  //implicit def file2RichFile(file:File) = new RichFile(file)
}

object MainApp{

  def main(args: Array[String]): Unit = {
    val file = new File("D:\\student.txt")
    //裝飾模式,顯示的增強(本來想實現:val contents = file.read(),但是卻使用RichFile的方式,所以是顯示的增強)
    val rf = new RichFile(file)
    val str = rf.read()
    print(str)
  }

}

使用隱式轉換方式

import java.io.File

import scala.io.Source

class RichFile(val file : File) {
  //定義一個read方法,返回String類型
  def read():String = Source.fromFile(file.getPath).mkString
}

object RichFile{
  //隱式轉換方法(將原有的File類型轉成了file類型,在用的時候需要導入相應的包)
  implicit def file2RichFile(file:File) = new RichFile(file)
}

object MainApp{

  def main(args: Array[String]): Unit = {
    //目的是使用File的時候不知不覺的時候直接使用file.read()方法,所以這里就要做隱式轉換
    val file = new File("D:\\student.txt")
    //導入隱式轉換,._將它下滿的所有的方法都導入進去了。
    import RichFile._
    //這里沒有的read()方法的時候,它就到上面的這一行中的找帶有implicit的定義方法
    val str = file.read()
    //打印讀取的內容
    println(str)
  }

}

(3)超人示例

class Man(val name:String)
class SuperMan {
  def fly(): Unit ={
    println("我要上天")
  }
}

object SuperMan{
  //隱式轉換,將Man轉換為SuperMan
  implicit def man2SuperMan(man:Man)=new SuperMan
  def main(args: Array[String]): Unit = {
    new Man("灰太狼").fly
  }
}

2、調用某個方法的時候,這個方法確實也存在,存入的參數類型不匹配

 售票廳賣票

老人和小孩是特殊人群,有單獨的買票窗口

//特殊人群(兒童和老人)
class SpecialPerson(var name:String)
//兒童
class Children(var name:String)
//老人
class Older(var name:String)
//青年工作者
class Worker(var name:String)

//特殊人群買票窗口
class TicketHouse{
  def buyTicket(p:SpecialPerson): Unit ={
    println(p.name + "買到票了")
  }
}

object MyPredef{
  //隱式轉換,將兒童轉換為特殊人群
  implicit def children2SpecialPerson(c:Children)=new SpecialPerson(c.name)
  //隱式轉換,將老人轉換為特殊人群
  implicit def older2SpecialPerson(o:Older)=new SpecialPerson(o.name)

}


object TestBuyTicket{
  def main(args: Array[String]): Unit = {
    //導入MyPredef類中的所有隱式轉換
    import MyPredef._
    val house = new TicketHouse
    //測試兒童買票
    val children = new Children("wangbaoqiang")
    house.buyTicket(children)
    //測試老人買票
    val older = new Older("xuzheng")
    house.buyTicket(older)
    //測試青年工作者買票
    val worker = new Worker("huangbo")
    //house.buyTicket(worker)//放開的話會報錯
  }
}

3、視圖邊界

 人狗之戀

class Person(val name : String) {
  def sayHello: Unit ={
    println("Hello, my name is " + name)
  }
  //2個人交朋友
  def mkFridens(p:Person): Unit ={
    sayHello
    p.sayHello
  }
}

class Student(name : String) extends Person(name)
class Dog(val name : String)
//聚會時2個人交朋友
class Party[T <% Person](p1:Person,p2:Person){
  p1.mkFridens(p2)
}

object Test{
  //隱式轉換,將狗轉換成人
  implicit def dog2Person(dog:Dog):Person={
    new Person(dog.name)
  }

  def main(args: Array[String]): Unit = {
    val huangxiaoming = new Person("huangxiaoming")
    val angelababy = new Student("angelababy")
    new Party[Person](huangxiaoming,angelababy)

    println("------------------------------------------------")

    val erlangshen = new Person("erlangshen")
    val xiaotianquan = new Dog("xiaotianquan")
    new Party[Person](erlangshen,xiaotianquan)
  }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM