您好,登錄后才能下訂單哦!
- 高階函數(shù)
- 閉包
- 模式匹配 可參考:https://blog.51cto.com/14048416/2337136
- 單一賦值
- 延遲計算
- 類型推導(dǎo)
- 尾部調(diào)用優(yōu)化
- 隱式轉(zhuǎn)化
這篇博文重點介紹:高階函數(shù)、閉包、隱式轉(zhuǎn)化。
高階函數(shù)主要有兩種:將一個函數(shù)當(dāng)做另外一個函數(shù)的參數(shù)和返回值是函數(shù)的函數(shù)。
高階函數(shù)的定義:
object Test01 {
def main(args: Array[String]): Unit = {
}
//1.函數(shù)作為參數(shù)
def sum1(f:(Int,Int)=>Int,x:Int,y:Int):Int ={
f(x,y)
}
//2.函數(shù)作為返回值
def sum2(x:Int)={
(y:Int)=>x+y
}
//3.柯里化寫法
def sum3(f:(Int,Int))(x:Int,y:Int) = f(x,y)
//4.使用隱式轉(zhuǎn)換的方式,傳入默認(rèn)值
def sum4(x:Int)(implicit y:Int=10) =x+y
}
函數(shù)的調(diào)用
object Test01 {
def main(args: Array[String]): Unit = {
//1.普通函數(shù)傳參
def func1(x:Int,y:Int) = x+y
println(func1(1,2))
//2.高階函數(shù)傳參以返回值是函數(shù)為例)
def func2(x:Int) = (y:Int) => x+y
//method one
val func22=func2(2)
println(func22(1))
//method two
println(func2(1)(2))
//3.高階函數(shù)改寫成柯里化方式傳入?yún)?shù)
def func3(x:Int)(y:Int) = x+y
//method one
val func33=func3(3) _
println(func33(2))
//method two
println(func3(5)(6))
//4.有默認(rèn)值時的調(diào)用
def func4(x:Int)(y:Int =10) = y+x
//method one 調(diào)用時,必須使用()()
println(func4(5)())
//method two
println(func4(5)(5))
//5.使用隱式參數(shù)在有默認(rèn)值時的調(diào)用
def func5(x:Int)( implicit y:Int =10) = y+x
//method one 調(diào)用時,必須使用()()
println(func5(5)())
//method two
println(func5(5)(5))
}
}
關(guān)于方法中的隱式參數(shù)
在聲明方法時,有某個參數(shù)使用了implicit修飾,并附加了默認(rèn)值。
object Test01 {
def main(args: Array[String]): Unit = {
//聲明一個有implicit修飾的參數(shù)的方法
def sum(x:Int)(implicit y:Int=10) =x+y
//1.碼運行的全局環(huán)境中不存在一個同類型的隱式變量,而且調(diào)用的時候,也沒有參入?yún)?shù)
println(sum(5)) //結(jié)果打?。?5
//2.如果全局環(huán)境中,存在一個同類型的隱式變量
implicit val num:Int=6
println(sum(5)) //結(jié)果打?。?1 ,這個全局的隱式變量值會替換方法定義中指定
//3.忽略所有的隱式變量值,可以由用戶直接傳入新的參數(shù)
println(sum(5)(5)) //結(jié)果打?。?0
}
}
注意:如果全局出現(xiàn)了多個同類型的隱式參數(shù):
implicit val abc:Int =6
implicit val aaa:Int =6
def sum(x:Int)(implicit y:Int =5) = x+y
println(sum(5))
此時這個段代碼會報錯:Error:(80, 16) ambiguous implicit values,所以,如果在方法中定義了隱式的參數(shù),那么在全局變量中只能有一個與方法中類型相同的隱式變量。
隱式參數(shù)的總結(jié):
- 隱式轉(zhuǎn)換會首先從全局中尋找,尋找不到,才使用隱式參數(shù)
- 如果隱式參數(shù)存在二義性,那么程序就報錯
閉包是一個函數(shù),返回值依賴與聲明在函數(shù)外部的一個或者多個變量。
閉包通常來講可以簡單的認(rèn)為是可以訪問一個函數(shù)里面局部變量的另一個函數(shù)。
例:
object Test01 {
def main(args: Array[String]): Unit = {
//定義一個閉包函數(shù)
def bibao() ={
var num:Int=0
//在閉包函數(shù)中定義一個函數(shù),用于修改變量num的值
val add=(x:Int)=>{
num+=x
num
}
//最終將這個函數(shù)返回
add
}
val result=bibao()
println(result(1)) //1
println(result(2)) //3
println(result(3)) //6
}
}
通過上面的案例我們了解到:每一次在調(diào)用result實際上是調(diào)用bibao方法中的add函數(shù),然后對bibao方法中的num變量進行疊加,實現(xiàn)了使用另一個函數(shù),訪問其他方法中的局部變量的功能,這個就是閉包。當(dāng)bibao調(diào)用的時候,就會申請一塊內(nèi)存區(qū)間,存儲了add和num變量,bibao這個函數(shù)當(dāng)被調(diào)用的時候,就返回了內(nèi)存的一個函數(shù)add,調(diào)用的時候,result(1),相當(dāng)于add(2),num的值就會被返回。當(dāng)然如果重新調(diào)用一次bibao方法,這個num變量會被重新初始化。
閉包的弊端 : 在一個線程中,或者一個程序中,不能太多的定義這樣的閉包函數(shù),定義閉包函數(shù)時,其中的局部變量一定不能太大。因為閉包中的局部變量時常駐內(nèi)存的,一旦定義之后,就一直在內(nèi)存中,除非程序終止。
scala的神奇之處:之前有過1 to 10 其實可以寫成 1.to(10),那其實就是表示:1 是一個 Int 類型的變量,所以證明 Int 類中會有一個 to 的方法,但事實上,我們在 Int 類型中根本就沒有尋找 to 方法,那也就是說對一個 Int 類型的變量 1 調(diào)用 Int 類型不存在的一個方法,這怎么還能正常運行 呢? 隱式轉(zhuǎn)換
dome01:
object Test01 {
def main(args: Array[String]): Unit = {
//定義一個傳入兩個Int類型的方法
def m1(x:Int,y:Int):Int ={
x+y
}
//定義一個Double的轉(zhuǎn)換成 Int類型 方法,隱式轉(zhuǎn)化引入這個方法
implicit def m2(x:Double) = x.toInt
//調(diào)用m1,并傳入double類型的值
println(m1(3.5,2.6)) //沒有報錯,正常打印
}
}
dome02:
def m1(x:Int,y:Int):Int ={
x+y
}
implicit def m2(x:Double) = x.toInt
println(m1(2.0,3.2))
當(dāng)一個類沒有某個方法的時候,但是此時調(diào)用這個方法,使用隱式轉(zhuǎn)換
以1.to(5)這個為例,1是一個int類型,但是Int中沒有定義to方法,但是richInt中定義了to方法調(diào)用了:1 to 10,其實是調(diào)用了:1.to(10),但是:Int 中沒有 to 方法,所以:去尋找引入的隱式轉(zhuǎn)換中有沒有能把 Int 類型轉(zhuǎn)換成能執(zhí)行 to 方法的類型,果然:在系統(tǒng)引入的轉(zhuǎn)換中發(fā)現(xiàn):implicit def intWrapper(x: Int): runtime.RichInt,所以:最終 int 類型的 1 就被轉(zhuǎn)換成了 RichInt 類型的變量
object Test01 {
def main(args: Array[String]): Unit = {
//導(dǎo)入MyFile的任意方法
import MyFile._
val file:File=new File("c://a.txt")
//調(diào)用了File的沒有的方法,而readAll是隱式轉(zhuǎn)換的RichFile的方法
file.readAll()
}
}
object MyFile{
//將File轉(zhuǎn)換為RichFile
implicit def m1(file:File):RichFile = new RichFile(file)
}
class RichFile(file:File){
def readAll(): String ={
Source.fromFile(file).mkString
}
}
方法參數(shù)類型不匹配時:
object Test01 {
def main(args: Array[String]): Unit = {
import ObjectImplicit._
def m1(worker:Worker) =println("person:"+worker.name)
m1(new Older("older"))
m1(new Worker("worker"))
m1(new Adult("adult"))
m1(new Young("young"))
}
}
class Older(val name: String)
class Young(val name: String)
class Worker(val name: String)
class Adult(val name: String)
object ObjectImplicit{
implicit def objectworker(obj: AnyRef): Worker ={
if(obj.getClass==classOf[Older]){
val older=obj.asInstanceOf[Older]
new Worker(older.name)
}else if(obj.getClass==classOf[Young]){
val young=obj.asInstanceOf[Young]
new Worker(young.name)
}else if(obj.getClass==classOf[Adult]){
val adult=obj.asInstanceOf[Adult]
new Worker(adult.name)
}else if(obj.getClass==classOf[Worker]){
val worker=obj.asInstanceOf[Worker]
worker
}else{
new Worker("Null")
}
}
}
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。