函數是一段完成某個事務的代碼片斷數組
func 函數名(參數列表) -> 返回值類型 {
// :TODO
return or not
}
* 函數的參數能夠省略,可是包裹着參數的 () 不能夠省略
* 返回值爲 -> void 的時候,意味着無返回值,-> void 也能夠省略
* 本質來講,函數和方法是同一種東西,只不過方法是定義在函數內部的函數,咱們稱之爲方法
複製代碼
從參數的有無
和 返回值的有無
能夠組成4種基本狀況bash
1.無參無返函數
好比:咱們想寫一個函數 打印字符串 "helloworld"
* Void v是大寫
func printAction() -> Void {
print("helloworld")
}
上面這段代碼無返回值,沒有return操做,能夠省略 -> Void,等價於
func printAction() {
print("helloworld")
}
printAction()
/// helloworld
複製代碼
2.無參有返post
// 沒有參數,返回值的類型 是 字符串String
func printAction() -> String {
return "Swift"
}
var str = printAction() // 接收返回值
print("\(str) 是最好的語言")
/// Swift 是最好的語言
複製代碼
3.有參有返ui
// 傳入 2個 Int 類型的參數,返回值也是 Int 類型
func printAction(num1: Int,num2: Int) -> Int {
return num1 + num2
}
printAction(num1: 2, num2: 3)
/// 5
複製代碼
4.有參無返spa
// 傳入一個 String 類型的參數,沒有返回值
func printAction(s1: String) {
print(s1)
}
printAction(s1: "Swift is ok")
/// Swift is ok
複製代碼
隱式返回
# 🐷:當函數 執行語句中的表達式 是 單一表達式的時候,咱們能夠省略return 字段
func printAction(num1: Int,num2: Int) -> Int {
return num1 + num2
}
上面函數等價於
func printAction(num1: Int,num2: Int) -> Int {
num1 + num2
}
複製代碼
6.多重返回指針
如今咱們想作這樣一件事,定義一個函數,傳入一個數組,返回2個值,一個最大,一個最小
func printAction(array: [Int]) -> (min: Int, max: Int) {
// 取出數組第一個,同時賦值給 當前最小值,最大值
var curMin = array[0]
var curMax = array[0]
// 從第二個開始遍歷,也就是下標1
for item in array[1..<array.count] {
if item < curMin {
curMin = item
} else if item > curMax {
curMax = item
}
}
return (curMin, curMax)
}
print(printAction(array: [1,2,3,4,5]))
/// (min: 1, max: 5)
複製代碼
可選返回類型
若是說上面的案例咱們傳入的數組是空呢?那麼在 訪問array[0]
的時候就會發生 運行時錯誤
code
因此咱們須要 定義 返回值爲可選型
,假如傳入的數組爲空時,咱們返回nil
事務
func printAction(array: [Int]) -> (min: Int, max: Int)? {
// 這裏咱們首先判斷是否爲空,爲空返回nil
if array.isEmpty {
return nil
}
var curMin = array[0]
var curMax = array[0]
for item in array[1..<array.count] {
if item < curMin {
curMin = item
} else if item > curMax {
curMax = item
}
}
return (curMin, curMax)
}
# 既然返回值是可選型,那麼咱們取值的時候就要注意了
* 返回值類型是 元祖,咱們能夠定義一個元祖去接收
* 若是元祖有值,咱們能夠進if,反之進else
var tuples = printAction(array: [])
if let result = tuples {
print(result.0,result.1)
} else {
print("我是空的")
}
複製代碼
每一個函數都包含 參數標籤
和 參數名稱
,而 參數標籤大大增長了代碼的可讀性
func someFuction(參數標籤 參數名稱: 參數類型) {
// do something
...
// 參數標籤 和 參數名稱 以 空格分隔
// 參數標籤能夠省略
}
複製代碼
好比說
func eatFuction(food: String, who:String) {
print("今天和\(who) 吃了\(food)")
}
eatFuction(food: "麻辣燙", who: "表弟")
// 這樣的調用 若是不明白函數內部實現的人,實際上是懵逼的
// foot 和 who 有什麼聯繫?
// 麻辣燙是表弟作的嗎?
* 若是加上參數標籤呢?
func eatFuction(eat food: String, with who:String) {
print("今天和\(who) 吃了\(food)")
}
那麼的調用就是這樣
eatFuction(eat: "kfc", with: "表弟")
// 今天和表弟一塊兒吃了kfc
// 有沒有一種豁然開朗的感受,沒錯 是我帶他吃的
複製代碼
若是咱們想省略一些參數,咱們並不想知道 參數表明的含義,可使用下劃線 _
來操做
並不關心這個參數
好比:
func eatFuction(_ food: String, _ who:String) {
print("今天和\(who) 吃了\(food)")
}
eatFuction("飯", "別人")
// 今天和別人吃了飯,我管你是誰
複製代碼
函數的參數中咱們是能夠添加默認值的,用來表達一些默認的值,也許不會修改
好比 去圖書館看書
# 含有默認值的參數列表,函數默認會提供2個初始化構造方法
# 一個包含默認值能夠改,一個不包含默認值
func defuleFuction(whichPlace: String, todo: String = "讀書") {
print("我天天都去\(whichPlace) \(todo)")
}
defuleFuction(whichPlace: "圖書館")
// 我天天都是圖書館看書
// 我只要寫地點,不須要寫幹什麼
* 假如我想更改這個默認值,
defuleFuction(whichPlace: "圖書館",todo: "看妹子")
// 那麼我也能夠去圖書館 看妹子呀
複製代碼
可變參數 顧名思義就是 參數是可變的,當咱們不肯定參數值的數量
時,能夠用 省略號...
來表示這個參數是可變的
// 咱們定義一個函數,累加咱們傳入的數值
func variableFuction(_ varialbeStrings: Int...,num: Int) -> Int {
var total = 0
for item in varialbeStrings {
total += item
}
return total + num
}
print(variableFuction(1,2, num: 3))
// 能夠看到 我把可變參數寫在了第一個參數,這樣是不建議的
# 注意
* 一個函數最多隻能擁有一個可變參數
* 有可變參數的時候 ,最好寫在後面,易讀
* 有可變參數的時候,另外的參數不能夠省略名稱
也就是說我這麼寫 是錯誤的 ❌
func variableFuction(_ varialbeStrings: Int...,_: Int) -> Int {
// 省略了num 報錯
複製代碼
輸入輸出參數 inout
這2段代碼咱們來看一下
// 傳入一個Int 分別加 1,而後返回
✅
func addFuction(num: Int) -> Int {
return num + 1
}
❌
func addOtherFuction(num: Int) -> Int {
num += 1
return num
}
# 🐷
# 事實上Swift 會默認認爲 全部可能的地方 都是 不可變的,畢竟是靜態語言
# 因此 函數的聲明中,參數默認都是 let 修飾的
第一種方法裏,num +1 ,至關於咱們建立了一個臨時變量
var temp = num + 1,咱們改變的是temp 的值
而第二種方法,咱們是在改變num 自身的值,這是不被容許的
那麼咱們顯示調用var ?
func addOtherFuction(var num: Int) -> Int {
num += 1
return num
}
# error: 'var' as a parameter attribute is not allowed,也是不能夠的
複製代碼
# 因此咱們引入了 inout,輸入輸出函數
默認狀況下,函數的參數傳遞是值傳遞,由於Int 是值類型
若是想改變函數外面的變量,則須要傳遞變量的地址
也就是 說 inout 的本質 是 引用傳遞
,將變量 的指針 經過& 符號
捕獲,而且修改指針指向的內存 裏的值
func addOtherFuction( num: inout Int) -> Int {
num += 1
return num
}
var num1 = 9
var num2 = addOtherFuction(num: &num1)
print(num1)
print(num2)
// num1 num2 都是10
# 必需要用 & 符號,相似c語言的取值符,但實際應該更爲複雜
複製代碼
每一個函數 都有本身的函數類型,它的函數類型 是由 參數類型
和 返回值類型
共同決定的
咱們能夠視這個類型爲一個總體
好比
func printAction(num1: Int,num2: Int) -> Int {
return num1 + num2
}
它的函數類型就是 (Int, Int) -> Int
複製代碼
這裏定義了一個addFuction,傳入2個數,相加並返回
func addFuction(a: Int, b: Int) -> Int {
return a + b
}
// 函數類型是 (Int, Int) -> Int
// 咱們把 上面的函數做爲參數 給到新的 函數
func newAddFuction(_ addName: (Int, Int) -> Int, a: Int, b: Int) {
print(addName(a,b))
}
能夠看到 addFuction這個參數 就是 (Int, Int) -> Int 類型的
那麼咱們調用的時候 ,是否是就能夠把 第一個函數 addFuction 傳給 newAddFuction
newAddFuction(addFuction, a: 2, b: 3)
# 咱們也能夠定義一個類型 指向這個類型
# 好比 var mathFunction: (Int, Int) -> Int = addFuction
那麼 newAddFuction 也能夠寫爲:
func newAddFuction(_ addName: (Int, Int) -> Int, a: Int, b: Int) {
print(addName(a,b))
}
newAddFuction(tempFunction, a: 2, b: 3)
複製代碼
把參數類型 在函數體內 當作一個總體 返回
func addFuction(a: Int, b: Int) -> Int {
return a + b
}
// 經過getAddFuction 拿到 addFuction
// 由於返回值類型 和 addFuction 類型同樣 都是 (Int, Int) -> Int
func getAddFuction() -> (Int, Int) -> Int {
return addFuction
}
let newAction = getAddFuction()
print(newAction(3,4))
複製代碼
後續還會在補充 還請多多指點
謝謝