函數類型
- 函數類型定義:(參數類型1,參數類型2,……)->返回值類型
- 函數類型是一種引用類型,類似于函數指針。可以將函數類型應用于任何使用類型的地方:變量、參數、返回值。
- 函數類型實例化支持:
- 全局函數
- 嵌套函數
- 成員函數(實例方法 與 靜態方法)
func add(x:Double, y:Double)->Double{
return x+y
}
func minus(x:Double, y:Double)->Double{
return x-y
}
func mulitiply(x:Double, y:Double)->Double{
return x*y
}
func divide(x:Double,y:Double)->Double{
return x/y
}
class Matrix{
var row=0.0
var column=0.0
init(row:Double ,colomn:Double){
self.row=row
self.column=column
}
func process(x:Double, y:Double)->Double{
return x*row+y*column
}
static func invoke(x:Double, y:Double)->Double{
return x*y+y*y
}
}
//函數類型作為變量
var compute:(Double, Double)->Double
compute=add //全局函數
let result1=compute(100,200)
compute=divide
let result2=compute(300,40)
var matrix=Matrix(row:10.0,column:20.0)
compute=matrix.process //實例方法
//compute.object=matrix
//compute.method=&process
compute(80,60)//JMP compute.method
compute=Matrix.invoke //靜態方法
compute(30,40)
//函數類型作為參數
func process(math: (Double,Double)->Double,x:double,y:Double){
let result=math(x,y)
print("result:\(result)")
}
process(multiply,x:30,y:50)
//函數類型作為返回值
func calculateFunction(symbol:String)->(Double,Double)->Double{
switch(symbol){
case "+":
return add
case "-":
return minus
case "*":
return multiply
case "/":
return divide
default:
return add
}
}
var calculate=calculateFunction("-")
let result3 = calculate(300,80)
//嵌套函數
func algorithmFunction(symbol:String)-> (Double, Double)->Double{
func add(x:Double, y:Double)->Double{
return x+y
}
func minus(x:Double, y:Double)->Double{
return x-y
}
func mulitiply(x:Double, y:Double)->Double{
return x*y
}
func divide(x:Double,y:Double)->Double{
return x/y
}
switch(symbol){
case "+":
return add
case "-":
return minus
case "*":
return multiply
case "/":
return divide
default:
return add
}
}
var algorithm=algorithmFuntion("/")
let result4 = algorithm(600,80)
函數類型的內存模型.png
compute=全局函數時,對象指針為空
認識閉包Closure
=====================
閉包是函數類型的實例,一段自包含的代碼塊,可被用于函數類型的變量,參數或返回值。
-
三種閉包形式:
- 全局函數:具名函數,但不捕獲任何值
- 嵌套函數:在函數內部嵌套定義具名函數,可捕獲包含函數中的值
- 閉包表達式:匿名函數類型實例,不具名的代碼塊,可捕獲上下文中的值
閉包是引用類型,閉包變量拷貝具有引用語義。
閉包和函數類型實例擁有同樣的內存模型。
class Rectangle {
var width=0
var length=0
init(width:Int, length:Int){
self.width=width
self.length=length
}
}
func <= (left: Rectangle, right: Rectangle) -> Bool {
return left.width*left.length<=right.width*right.length
}
func compare(first:Rectangle, second: Rectangle)->Bool{
return first.width*first.length<=second.width*second.length
}
var rects = [Rectangle(width:6,length:7),
Rectangle(width:5,length:8),
Rectangle(width:9,length:6)]
//函數類型對象
/*
func sort(@noescape isOrderedBefore: (Self.Generator.Element,Self.Generator.Element) -> Bool) -> [Self.Generator.Element]
*/
//func sort(isOrderedBefore:(Rectangle,Rectangle)->Bool)->[Rectangle]
var predict: (Rectangle,Rectangle)->Bool
predict=compare
rects.sort(predict)
rects.sort(compare) //不用上面那樣繞
//閉包表達式
rects.sort({(first:Rectangle, second:Rectangle)->Bool in
return first.width*first.length<=second.width*second.length
})
let expression={(first:Rectangle, second:Rectangle)->Bool in
return first.width*first.length<=second.width*second.length
}
rects.sort(exprssion)//也可以這么寫
//自動類型推斷
rects.sort({first,second in
return first.width*first.length<=second.width*second.length
})
//單表達式省略return
rects.sort({first,second in first.width*first.length<=second.width*second.length})
//參數縮略形式
rects.sort({$0.width*$0.length<=$1.width*$1.length})
//操作符縮略式
rects.sort( <= ) //rects.sort(compare)
//尾隨閉包
rects.sort{
first,second in
first.width*first.length<=second.width*second.length
}
rects.sort{$0.width*$0.length<=$1.width*$1.length}
//自動閉包
var cities = ["Beijing","shanghai","New York","Paris","London"]
print(cities.count)
let filter = {cities.removeLast()}//()->String
print(cities.count)
print("Deleting\(filter())!")
print(cities.count)
閉包表達式
{(參數1,參數2……)->返回值類型 in
語句塊
}
- 幾種簡化縮寫形式:
- 自動類型推斷:省略參數類型和返回值類型
- 單表達式閉包可以省去return關鍵詞。
- 使用參數縮略形式$0,$1...省略參數聲明和in
- 將操作符函數自動推導為函數類型
- 尾隨閉包:當閉包表達式為函數最后一個參數,可將其寫在括號后
- 自動閉包:不接受任何參數,直接返回表達式的值。允許延遲計算
函數類型與閉包的變量捕獲
-
函數類型和閉包可以捕獲其所在上下文的任何值:
- 函數參數
- 局部變量
- 對象實例屬性
- 全局變量
- 類的類型屬性
如果捕獲值生存周期小于閉包對象(參數和局部變量),系統會將被捕獲的值封裝在一個臨時對象里,然后在閉包對象上創建一個對象指針,指向該臨時對象。
臨時對象和閉包對象之間是強引用關系,生存周期跟隨閉包對象。
var data=100
//捕獲實例屬性
class Rectangle{
var width=0
var length=0
static var max=100
init(width:Int,length:Int){
self.width=width
self.length=length
}
func getComputeHandler()->() -> Int{
return {
return self.width*self.length
}
}
}
var rect=Rectangle(width:10,length:20)
var handler=rect.getComputeHandler()
handler()
//捕獲參數或局部變量
func addHandler(var step: Int) -> () -> Int {
var sum = 0
return {
sum += step
data++
Rectangle.max++
step++
return sum
}
/* func add() ->Int {
sum+=step
return sum
}
return add*/
}
let addByTen=addHandler(10)
addByTen()
addByTen()
addByTen()
print(data)
print(Rectangle.max)
let addBYSix=addHandler(6)
addBySix()
addBySix()
addBySix()
print(data)
print(Rectangle.max)
/*class AddHelper {
var sum=0
var step=0
func add() -> Int {
self.sum+=self.step
return self.sum
}
}
func addHandlerHelper(step: Int) -> () -> Int {
let sum=0
let obj=AddHelper()
obj.sum=sum
obj.step=step
let closuer=obj.add
return closuer
}
let addByTen=addHandlerHelper(10)
print(addByTen())
print(addByTen())
print(addByTen())
let addByTen=addHandlerHelper(6)
print(addBySix())
print(addBySix())
print(addBySix())*/
捕獲值的內存模型.png