Swift -- 6.函数和闭包
函數(shù)
/*
函數(shù)分為函數(shù)名,參數(shù),返回值,執(zhí)行代碼塊四部分
有返回值函數(shù)可以作為一個值直接在print里輸出?
*/
?
//函數(shù)定義
func max(a:Int, b:Int, c:Int) -> Int
{
? ? return 1
}
max(1, b: 2, c: 3)
?
func firstMethod(str:String) ->String
{
? ? return "123"
}
print(firstMethod("123"))
?
?
//沒有返回值的函數(shù)
func noReturn(str:String)
{
? ? print("no return")
}
?
?
//多個返回值的函數(shù)
func mutableReturn(str:String) ->(String, String)
{
? ? return ("1", "2")
}
?
func mutableReturnWithName() ->(height:Int, weight:Int)
{
? ? return (1, 2)
}
var man = mutableReturnWithName()
print(man.height)
?
//函數(shù)調(diào)用本身? 也就是遞歸
func doAgain(num:Int) -> String
{
? ? if num > 5{
? ? ? ? print("000")
? ? ? ? return "\(doAgain(num - 1))"
? ? }else{
? ? ? ? return "fff"
? ? }
}
print(doAgain(10))
/*
遞歸是非常有用的,例如程序希望遍歷某個路徑下的所有文件,但這個路徑下的文件夾的深度是未知的,那就可以使用遞歸來實現(xiàn)這個需求。系統(tǒng)可以設(shè)定一個函數(shù),改函數(shù)接受一個文件路徑作為參數(shù),該參數(shù)可遍歷出當(dāng)前路徑下的所有文件和文件路徑--該函數(shù)再次調(diào)用函數(shù)本身來處理該路徑下的所有文件路徑
*/
?
?
/*
函數(shù)的參數(shù)
第一個參數(shù)如果不寫外部參數(shù),是不會顯示外部參數(shù)的,第二個和之后的參數(shù)如果不寫外部參數(shù),會自動默認(rèn)外部參數(shù)和內(nèi)部參數(shù)同名
也就是說,除了第一個參數(shù),其他的參數(shù)就算不設(shè)置外部參數(shù)也會有外部參數(shù)
?
*/
//擁有外部參數(shù)名的函數(shù)
func haveWaiName(wainame neiname:String) ->String
{
? ? print(neiname)
? ? return "\(neiname)"
}
print(haveWaiName(wainame: "name"))
?
//外部形參名和內(nèi)部形參名一樣的函數(shù)
func havesameName(name name:String) ->String
{
? ? return name
}
print(havesameName(name: "sarah"))
?
//只有一部分形參有外部形參名的函數(shù)
func justSomehavename(name name:String, years:Int) -> (String, Int)
{
? ? return (name, years)
}
print(justSomehavename(name: "marry", years: 10).0)
?
//形參有默認(rèn)值的函數(shù) 一般將帶有默認(rèn)值的形參放在最后面,下面這個并不是一個好的編程習(xí)慣
func valueAlready(user name:String = "marry", msg:String)
{
? ? print("\(name),\(msg)")
}
valueAlready(msg: "hi")
valueAlready(user: "tom", msg: "hi")
?
//參數(shù)個數(shù)可變的函數(shù)
func varibleValue(a:Int, books:String..., name:String)
{
? ? for tmp in books
? ? {
? ? ? ? print(tmp)
? ? }
}
varibleValue(3, books: "java","swift", name: "string")
/*
數(shù)量可變的參數(shù)的本質(zhì)是一個數(shù)組參數(shù),在執(zhí)行代碼塊中當(dāng)做一個數(shù)組來使用
*/
?
?
/*
函數(shù)中的形參默認(rèn)是常量,如果想要變量的形參,需要自己聲明
*/
func mutableNum(var name:String) ->String
{
? ? name = name + "sss"
? ? return name
}
print(mutableNum("mother"))
?
?
/*
在函數(shù)中,傳入的參數(shù)如果是值類型,則傳進去的是該值的副本,在函數(shù)中不會對原來的值產(chǎn)生影響
如果想要在函數(shù)中對該值進行改變,可以使用inout標(biāo)簽來標(biāo)注
*/
func inoutFunc(inout age:Int) ->Int
{
? ? age = age + 1
? ? return age
}
var age = 5
print(age)//5
print(inoutFunc(&age))//6
print(age)//6
/*
當(dāng)參數(shù)是引用類型的時候,程序會賦值引用的副本,不會復(fù)制該引用指向的對象
所以,當(dāng)參數(shù)是引用類型的時候,即使不適用inout標(biāo)簽,該值仍然會在函數(shù)中被修改
但是,如果在函數(shù)中將引用類型置為空,只會切斷副本和指向?qū)ο笾g的聯(lián)系,在函數(shù)之外,該值仍然不為空
*/
class DataWrap
{
? ? var a:Int = 0
? ? var b:Int = 0
}
func swap(var dw:DataWrap!)
{
? ? var tmp = dw.a
? ? dw.a = dw.b
? ? dw.b = tmp
? ? tmp = 0
? ? dw = nil
}
var wp:DataWrap! = DataWrap()
print(wp)
swap(wp)
print(wp)//wp沒有被置為空,但是如果使用了inout標(biāo)簽,這里就會出錯
?
?
?
//定義一個函數(shù)變量
var myfun : (Int, Int) ->Int //這里最好不要給參數(shù)命名,雖然也可以命名,但是在使用的時候系統(tǒng)不會提示
var test : (String) ->Void
func pow(base base:Int, exponent:Int) ->Int
{
? ? var result = 1
? ? for _ in 1...exponent
? ? {
? ? ? ? result *= base
? ? }
? ? return result
}
//將pow函數(shù)賦值給mufun,則myfun可以當(dāng)成pow使用
myfun = pow
print(myfun(3,4))
/*
只要被賦值的函數(shù)類型與myfun的變量類型一致,程序就可以賦值成功
通過使用函數(shù)類型的變量,可以讓myfun在不同的時間指向不同的函數(shù),從而讓程序更加靈活。
*/
?
?
//其中一個參數(shù)是函數(shù)的函數(shù)
func map(var data data:[Int],fn:(Int) ->Int) ->[Int]
{
? ? for var i = 0, len = data.count; i<len ;i++
? ? {
? ? ? ? data[i] = fn(data[i])
? ? }
? ? return data
}
func square(val:Int) ->Int
{
? ? return val*val
}
func cube(val:Int) ->Int
{
? ? return val*val*val
}
var data = [1,2,3]
print(map(data: data, fn: square))
print(map(data: data, fn: cube))
//這種方式可以動態(tài)的改變一個函數(shù)中的部分代碼塊,類似于c中的函數(shù)指針
?
?
//返回值為函數(shù)的函數(shù)
func getMathFunc(type type:String) -> (Int) ->Int
{
? ? switch(type)
? ? {
? ? case "square":
? ? ? ? return square
? ? default:
? ? ? ? return cube
? ? }
}
var mathFunc = getMathFunc(type: "cube")
print(mathFunc(5))
?
/*
函數(shù)重載
函數(shù)名相同,但是參數(shù)個數(shù)不同或外部參數(shù)名稱不同或返回值不同
這種情況就是重載
*/
?
?
/*
嵌套函數(shù)
在swift中,函數(shù)和類享有同樣的級別,函數(shù)可以直接聲明在文件里,而不用單獨聲明在一個類里
所以,函數(shù)可以當(dāng)成變量被引用,被返回,在函數(shù)中聲明函數(shù)
*/
func getMathFunc2(type type:String) ->(Int) ->Int
{
? ? func square(val: Int) ->Int
? ? {
? ? ? ? return val*val
? ? }
? ? func cube(val:Int) ->Int
? ? {
? ? ? ? return val*val*val
? ? }
? ? switch(type)
? ? {
? ? case "square":
? ? ? ? return square
? ? default:
? ? ? ? return cube
? ? }
}
?
?
?
閉包
//本質(zhì)是功能更靈活的代碼塊,可以直接作為返回值被返回
//在閉包里不要給參數(shù)寫外部參數(shù)名,因為Xcode不會提示,還要自己寫,很麻煩
var square3 = {
? ? (val:Int) -> Int in
? ? return val*val
}
print(square3(5))
?
//在閉包的后面添加圓括號來調(diào)用閉包
var resultt2 = {
? ? (base:Int,exponent:Int) -> Int in
? ? var result = 1
? ? for _ in 1...exponent
? ? {
? ? ? ? result *= base
? ? }
? ? return result
}(3, 4)
?
print(resultt2)
?
//省略形參類型,返回值類型的閉包
var square4:(Int) ->Int = {(val) in return val*val}
//省略了參數(shù)類型,參數(shù)列表的那個圓括號也可以省略
var square6:(Int) ->Int = {val in return val*val}
print(square6(5))
var result3:Int = {base, exponent in
? ? var result = 1
? ? for _ in 1...exponent
? ? {
? ? ? ? result *= base
? ? }
? ? return result
}(4, 3)//因為這個地方有聲明int類型的變量,所以不用指定返回值類型
//上面兩個閉包因為有聲明閉包類型變量,所以也可以不聲明返回值
?
//省略return
//如果閉包表達(dá)式的執(zhí)行體只有一行代碼,而且這行代碼的返回值將作為閉包表達(dá)式的返回值,那么swift允許省略return關(guān)鍵字
var square7:(Int) ->Int = {val in val*val}
var square8 = {(val:Int) -> Int in val*val*val}
print(square7(3))
print(square8(3))
?
//省略形參名
var square9:(Int) ->Int = {$0 * $0}
var result4:Int = {
? ? var result = 1
? ? for _ in 1...$0
? ? {
? ? ? ? result *= $1
? ? }
? ? return result
}(3, 4)
?
//尾隨閉包
//當(dāng)函數(shù)的最后一個參數(shù)是一個函數(shù)類型的時候,可以用閉包來進行傳參,然后把小括號放在閉包前面,把閉包給單獨放置在外面
func map2(var data data:[Int], fn:(Int) -> Int) -> [Int]
{
? ? for var i = 0, len = data.count; i<len; i++
? ? {
? ? ? ? data[i] = fn(data[i])
? ? }
? ? return data
}
var data2 = [3, 4, 5, 6, 7]
print("原數(shù)據(jù)\(data2)")//"原數(shù)據(jù)[3, 4, 5, 6, 7]\n"
var rvt1 = map2(data: data2){$0 * $0}
var rvt3 = map2(data: data2){
? ? var result = 1
? ? for index in 2...$0
? ? {
? ? ? ? result *= index
? ? }
? ? return result
}
//如果調(diào)用函數(shù)時只需要閉包表達(dá)式一個參數(shù),那么使用尾隨閉包時,swift甚至允許程序省略調(diào)用函數(shù)的圓括號
?
//閉包可以捕獲上下文中的變量和常量
//每個閉包都會持有一個它所捕獲的變量的副本,所以,閉包執(zhí)行與原來所在的函數(shù)并沒有聯(lián)系
//閉包是引用類型,所以即使是聲明成常量也可以改變內(nèi)部值
func makeArray(ele:String) -> () ->[String]
{
? ? var arr:[String] = []
? ? func addElement() ->[String]
? ? {
? ? ? ? arr.append(ele)
? ? ? ? return arr
? ? }
? ? return addElement
}
let add1 = makeArray("sun")
print(add1())
print(add1())
let add2 = makeArray("zhu")
print(add2())
print(add2())
轉(zhuǎn)載于:https://www.cnblogs.com/chebaodaren/p/5501563.html
總結(jié)
以上是生活随笔為你收集整理的Swift -- 6.函数和闭包的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原创:三星堆文化比中原文化先进,真的比夏
- 下一篇: java 中的2个接口 Comparab