函数是一段完成某个事务的代码片断数组
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))
复制代码
后续还会在补充 还请多多指点
谢谢