從頭學習大數據培訓課程 scala 對象與函數式編程(四)scala 基礎 4

隱式轉換

作用:能夠豐富現有類庫的功能,對類的方法進行增強

隱式轉換函數

以implicit關鍵字聲明並帶有單個參數的函數

比如1 to 10其實是調用的1.to(10)這個方法

但是在Int類中並沒有to這個方法

int 的to方法實際上是調用RichInt里的intWrapper方法,最終調用的是RichInt里的to方法

intWrapper就是以implicit關鍵字聲明並帶有單個參數的函數,intWrapper就是一個隱式轉換函數

predef這個類就是預定義的predefine的簡寫

在shell中用:implicit -v來查看,默認有多少個隱式轉換函數

在2.11.8中有69個隱式轉換,scala升級比較快所以其它版本可能不同

隱式轉換函數其實用到了裝飾模式

裝飾模式對應的是門面模式

隱式轉換練習:

給代表文件地址的字元串增加一個可以讀文件的功能

import scala.io.Source

class ImplicitFunctionDemo(val path:String) {

def read():String = {

Source.fromFile(path).mkString

} }

object ImplicitFunctionDemo{

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

val path = "C:\Users\Leo.He\Desktop\抽取項目描述.txt"

val content: String = new ImplicitFunctionDemo(path).read() println(content) } }

這是一個顯示的調用並不是一個隱式的調用,這是我們平時開發過程中常用的方法

隱式轉換函數的實現方法

1.首先在MyPredef寫一個String的隱式轉換函數

object MyPredef {

implicit def pathStringToImplicitFunction(path:String) = new ImplicitFunctionDemo(path) }

2.然後修改剛才的類為隱式轉換的調用方式,在使用隱式轉換中String類型的path變數就有了read方法,這個read實現上是ImplicitFunctionDemo的read。這個轉換過程是由MyPredef里的隱式轉換函數完成的

import scala.io.Source

class ImplicitFunctionDemo(val path:String) {

def read():String = {

Source.fromFile(path).mkString

} }

object ImplicitFunctionDemo{

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

val path = "C:\Users\Leo.He\Desktop\抽取項目描述.txt"

val content: String = new ImplicitFunctionDemo(path).read() println(content)

import MyPredef.pathStringToImplicitFunction

val content1 = path.read() println(content1) } }

隱式轉換與柯里化的使用shell中柯里化與隱式轉換使用的例子

/**

* 這裡用到了隱式轉換、隱式值、柯里化(隱式參數)、內部類、泛型、特質、比較的方法、重寫toString方法

* 首先import OrderingDemo.OrderStudent

* OrderStudent是Ordering[HainiuStudent]的子類

* 所以demo.comp() 柯里化方法(def comp()(implicit ord:Ordering[HainiuStudent])) 第二個參數會匹配到OrderStudent

* 所以ord的值傳入的是OrderStudent

* ord.gt(v1,v2)調用的是OrderStudent的gt方法也就是ordering的gt方法(def gt(x: T, y: T): Boolean = compare(x, y) > 0)

* ordering的gt方法中調用的是compare,但OrderStudent是ordering的子類實現,所以調用的是orderStudent的compare方法

* 由OrderStudent的compare方法返回會的正負值決定了返回true還是false,(Boolean = compare(x, y) > 0) 大於0是true小於0是false

* demo.comp()(def comp()(implicit ord:Ordering[T]))方法返回比較之後的對象

* println(student)列印了對象重寫的toString方法(override def toString: String = s"name:$name,age:$age")的返回值

*/

object OrderingDemo {

implicit object OrderStudent extends Ordering[HainiuStudent]{

override def compare(x: HainiuStudent, y: HainiuStudent): Int = if(x.age > y.age) 1 else -1 } } class CompareDemo[T:Ordering](val v1:T,val v2:T){

def comp()(implicit ord:Ordering[T]) = if(ord.gt(v1,v2)) v1 else v2

}

object CompareDemo{

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

import OrderingDemo.OrderStudent

val s1 = new HainiuStudent("牛1",24)

val s2 = new HainiuStudent("牛2",23)

val demo = new CompareDemo[HainiuStudent](s1,s2) // val demo = new CompareDemo(s1,s2) //簡寫的方式

val student: HainiuStudent = demo.comp() println(student) } } class HainiuStudent(val name:String,val age:Int){

override def toString: String = s"name:$name,age:$age" }

泛型:泛型就是不確定的類型,可以在類或方法不確實傳入類型時使用,可以提高代碼的靈活性和復用性scala中泛型的用法和java中差不多,但是會有一些自己獨特的語法

比如說ordering中泛型的一些特殊符號

這個叫ViewBound

這個叫UpperBound

泛型:

[B <: A] UpperBound 上界,B類型的父類是A類型

[B >: A] LowerBound 下界,B類型的子類是A類型

[B <% A] ViewBound B類型轉換成A類型,需要一個隱式轉換函數

[B : A] ContextBound 需要轉換成A[B]類型,需要一個隱式轉換的類型

[-A] 逆變,作為參數類型,T是A的子類

[+B] 協變,作為返回類型,T是B的父類

UpperBound

class UpperBoundDemo[T <: Comparable[T]] {

def choose(a:T,b:T):T = { if(a.compareTo(b) > 0) a else b

} }

object UpperBoundDemo{

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

val u = new UpperBoundDemo[HaniuEngineer]

val h1 = new HaniuEngineer("牛大",20)

val h2 = new HaniuEngineer("牛二",22) println(u.choose(h1,h2)) } } class HaniuEngineer(val name:String,val age:Int) extends Comparable[HaniuEngineer]{

override def compareTo(o: HaniuEngineer): Int = {

this.age - o.age //SCALA中訪問本類的屬性也可以用this }

override def toString: String = {

s"${name}我年紀大" } }

ViewBound

class ViewBoundDemo[T <% Ordered[T]] {

def choose(work1:T,work2:T):T={ if(work1 > work2) work1 else work2

} }

object ViewBoundDemo{

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

import MyPredef.selectWork

val demo = new ViewBoundDemo[HainiuWork]

val work1 = new HainiuWork("金融",20000,10)

val work2 = new HainiuWork("互聯網",20000,6) print(demo.choose(work1,work2)) } } class HainiuWork(val company:String,val money:Int,val holiday:Int){

override def toString: String = {

s"go to $company,happy holiday $holiday" } }

隱式轉換函數實現

object MyPredef {

implicit val selectWork = (s:HainiuWork) => new Ordered[HainiuWork]{

override def compare(that: HainiuWork) = { if(s.money == that.money){

s.holiday - that.holiday

}else{

s.money - that.money

} } } }

ContextBound

//T:Ordering 需要一個隱式轉換是Ordering[T]類型的 class ContextBoundDemo[T:Ordering] {

def choose(work1:T,work2:T):T={

val ord:Ordering[T] = implicitly[Ordering[T]] //import MyPredef.SelectWorkObject Ordering[HainiuWork] //implicitly[Ordering[HainiuWork]](implicit e: Ordering[HainiuWork]) = e //(implicit e: Ordering[T]) = e //def implicitly[HainiuWork](implicit e: HainiuWork) = e //val ord:Ordering[HainiuWork] = MyPredef.SelectWorkObject if(ord.gt(work1,work1)) work1 else work2

} }

object ContextBoundDemo{

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

import MyPredef.SelectWorkObject

val demo = new ContextBoundDemo[HainiuWork]

val work1 = new HainiuWork("金融",20000,6)

val work2 = new HainiuWork("互聯網",19000,6) println(demo.choose(work1,work2)) } }

隱式轉換類型實現

object MyPredef {

implicit object SelectWorkObject extends Ordering[HainiuWork]{

override def compare(s: HainiuWork, that: HainiuWork): Int = { if(s.money == that.money){

s.holiday - that.holiday

}else{

s.money - that.money

} } } }

版權聲明:原創作品,允許轉載,轉載時務必以超鏈接的形式表明出處和作者信息。否則將追究法律責任。來自海牛學院-青牛


推薦閱讀:

分答和在行到底值不值1個億美金?
「互聯網金融&大數據風控」結合的九大維度
大數據計數原理1+0=1這你都不會算(九)No.64
數據分析不只Tableau,這款國產工具也能扛上一扛!

TAG:大數據 | 大數據處理 | Scala |