从 函数 到 Swift

函数是一段完成某个事务的代码片断数组

定义

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
复制代码

5.隐式返回

# 🐷:当函数 执行语句中的表达式 是 单一表达式的时候,咱们能够省略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)
复制代码

7.可选返回类型

若是说上面的案例咱们传入的数组是空呢?那么在 访问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("我是空的")
}
复制代码

可选绑定 if let 介绍内存

函数的标签以及参数

每一个函数都包含 参数标签参数名称,而 参数标签大大增长了代码的可读性

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))
复制代码

后续还会在补充 还请多多指点

谢谢

相关文章
相关标签/搜索