一、概念
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) } }