Swift基础入门知识学习(10)-函数(函式)-讲给你懂

本文详细介绍了Swift编程中的函数概念,包括函数定义、参数使用、参数标签、预设参数值、输入输出参数、返回值以及函数类型。通过实例解析了如何创建和调用函数,以及如何处理函数参数和返回值,帮助读者深入理解Swift中的函数操作。
摘要由CSDN通过智能技术生成

Swift基础入门知识学习(9)-条件语句-讲给你懂


函数定义

理解难度
★★★☆☆
实用程度
★★★★★

函数(function)是一个独立的代码区块,用来完成特定任务。当你需要一个多次使用到的功能时,重复代码通常不是个好主意。函数帮助我们避免这样的问题。把这个功能写成一个函数可以简化代码。

  • 函数声明: 告诉编译器函数的名字,返回类型及参数。
  • 函数定义: 提供了函数的实体。

函数命名的方式与常数变数一样,但名称后面需要加上小括号( )(像是前面章节很常使用的print(),就是一个内建的函数。建立一个函数要使用func关键字,函数格式如下:

func 函数名称(参数: 参数类型) -> 返回值类型 { 

    内部执行的程式
    
    return 返回值
}

Swift函数从 func 关键字开始,然后是函数名称,然后打开和关闭括号。你的函数的所有主体在请求函数时,应该运行的代码都放置在大括号内。

定义函数的时候,可以指定一个或多个输入参数和一个返回值类型。

每个函数都有一个函数名来描述它的功能。通过函数名以及对应类型的参数值来调用这个函数。函数的参数传递的顺序必须与参数列表相同。

函数的实参传递的顺序必须与形参列表相同,-> 后定义函数的返回值类型。

依据上述介绍,你可以为一个函数设置传入的参数与返回值,但也可以依据需求不设置参数与返回值,如下为一个最简单的函数格式:

func 函数名称() {

    // 内部执行的程式
    
}

没有参数也没有返回值,以下是一个例子:

// 建立一个函数
func simpleOne() {
    print("It is a simple function .")
}

// 呼叫函数
simpleOne()
// 打印:It is a simple function .

这样就会执行函数内的程式。这就是一个最简单的功能。

函数中应该写什么代码?

三个时机点就应该创建自己的函数:

  1. 最常见的情况是,在不同的地方想要相同的功能。在这里使用函数意味着你可以只更改一段代码,所有使用同一个函数的任何地方都会更新。
  2. 函数也可用来分解代码。如果有一个很长函数,可能不容易调试现在的进程;但如果将其分解为三到四个较小的函数,那么就更容易追踪了。
  3. 最后一个原因是更进阶的。Swift允许我们从现有函数中构建新函数,称为函数嵌套。通过将进程拆分为多个小函数,函数组合使我们能够通过以各种方式组合这些小函数来构建大函数,有点像组合积木一样。

函数参数

理解难度
★★★★☆
实用程度
★★★★★

Swift允许你将值发送到函数,然后该函数可以在函数里面用于更改其行为方式。以这种方式发送到函数的值称为参数。

函数可以传入参数(parameter),定义函数的参数时,必须明确标注类型,然后就会将参数指派成一个常数,格式如下:

func 函数名称(参数指派给的常数: 类型标注) {

    // 内部执行的程式
    
}

以下是一个例子:

// 建立函数 有一个类型为 Int 的参数
// 函数的功能是将带入的参数加一 并打印来
func addOne(数字: Int) {
    // number 即为被指派参数的常数 只能在函数内部范围内使用
    print(数字 + 1)
}

// 呼叫函数 传入整数 12

addOne(数字: 12)

这里的“数字”是由自己命名的。最好名称命名要清楚合理,至少得要自己看得懂。一看就明白才是好代码。

想想看,现在打印的结果是什么?

多重参数函数

函数如果有超过一个参数时,要依序将参数填入,并以逗号 , 隔开,以下例子:

// 建立有两个参数的函数 参数的类型分别为 String 及 Int
func hello(name: String, age: Int) {
    print("\(name) is \(age) years old .")
}

// 呼叫函数
hello(name: "Jack", age: 25)

一个函数应该接受多少参数?

一个函数可以不带参数或带 20 个参数。这是一个没有“绝对”而难回答的东西。

但是一个函数需要许多参数时…也许六个或更多,这是非常主观的问题…你需要开始想想,这个函数是不是做了太多的工作了?复杂化了?

  • 真的需要所有的参数吗?
  • 是不是可以把这个函数拆分为参数少一点的小函数?
  • 这些参数是不是可以以某种方式分组呢?

函数参数名称与标签

理解难度
★★☆☆☆
实用程度
★★☆☆☆

每个函数的参数的完整定义方式,都包含参数标签(argument label)及参数名称(parameter name)。

  1. 参数标签用于呼叫函数时,标注给函数的参数。
  2. 参数名称用于函数内部操作。

以下为一个有参数标签及参数名称的函数格式:

func 函数名称(参数标签1 参数名称1: 类型1,
  参数标签2 参数名称2: 类型2) {
  
    // 内部执行的程式
    
}

以下为一个例子:

func hello2(name n: String, age a: Int) {
    // n 跟 a 为参数名称 在函数内部使用
    print("\(n) is \(a) years old .")
}

// name 跟 age 为参数标签 呼叫函数时要标注在参数之前
hello2(name: "Jack", age: 25)

虽然在这里介绍这个标签的技巧,但是说实在的,何必找自己的麻烦呢!

省略参数标签

理解难度
★★☆☆☆
实用程度
★★★★☆

如果呼叫函数时想要省略参数标签(argument label),定义函数时只要使用下底线_来替代参数标签即可,以下为一个例子:

// 参数标签使用下底线 _ 替换
func hello3(_ name: String, _ age: Int) {
    print("\(name) is \(age) years old .")
}

// 呼叫函数时 就可以不用写参数标签
hello3("Jack", 33)

这个技巧倒是实用多了。

或是在定义函数时省略参数标签,这样就可以将参数名称当作参数标签使用,如下:

// 使用函数的参数名称作为参数标签 这边就是 name 与 age
func hello4(name: String, age: Int) {
    print("\(name) is \(age) years old .")
}

// 呼叫函数时 使用的参数标签即为参数名称
hello4(name: "Jack", age: 25)

Swift 会这样稍微复杂的设计函数参数名称,是为了让呼叫函数时,语意可以更明显,以下是一个例子:

func sayHello(to name: String, and name2: String) {
    print("Hello \(name) and \(name2) !")
}
// 参数标签设为 to 跟 and
// 这行看起来就像个完整的英文句子 可以明显的知道这个函数要干嘛
sayHello(to: "Joe", and: "Amy")

总之,管他是标签还是名称,一个已经足够,何必用两个来混乱自己呢?不要这样做了。

预设参数值

理解难度
★★★☆☆
实用程度
★★★☆☆

可以对函数的参数设定一个预设值,如果未传入值时,则内部就使用这个预设值。就像这样:

func someFunction(number: Int = 12) {
    print(number)
}

// 打印:6
someFunction(number: 6)

// 如果没有传入值 则会使用预设值 打印:12
someFunction()
  • 一个函数只能有一个可变数量参数。
  • 函数如果有预设值参数,也有可变数量参数时,必须把可变数量参数放在参数列表的最后。

输入输出参数

理解难度
★★★★★
实用程度
★☆☆☆☆

普通函数的参数使用范围都只在函数程式体内,如果想要一个可以修改参数的函数,并在呼叫函数结束后,这个修改仍然存在,则必须将参数设定为输入输出参数( In-Out Parameters )。使用方式为:

  • 定义函数时,在参数类型前加上inout。此参数不能有预设值,也不能再设为可变数量参数。
  • 当呼叫函数,传入的参数作为输入输出参数时,需要在参数前加上&。这个参数只能是一个变数,不能是常数、字面量(单纯的数值或字串)。

以下是个例子:

// 定义一个[有一个输入输出参数]的函数 参数类型前要加上 inout
func newNumber(number: inout Int) {
    number *= 2
}

var n = 10
print(n) // 这时 n 为 10

// 传入的参数在函数结束后 改变仍然存在
newNumber(number: &n)

print(n) // 所以这时再打印 就会是 20

函数返回值

理解难度
★★★☆☆
实用程度
★★★★☆

函数除了可以传入参数,同时也可以返回值,使用方式是在函数( )后面接着一个减号跟大于组成的箭头 -> ,然后再接着写返回值的类型标注,函数内部要使用 return 语句后接着返回值来返回。使用 return 后会随即终止函数的动作,函数内部其后的程式都不会继续执行。

以下例子:

// 定义函数 有一个类型为 Int 的参数以及一个类型为 Int 的返回值
// 函数的功能是将带入的参数加十 并返回
func addTen(number: Int) -> Int {
    let n = number + 10
    // 使用 return 来返回值 这个返回值的类型要与上面标注的相同
    return n
}

// 呼叫函数 传入整数 12 会返回 22
let newNumber = addTen(number: 12)

print(newNumber)

想想看,现在打印的结果是什么?

没有返回值函数

理解难度
★★☆☆☆
实用程度
★★★★☆

下面是 runoob(_😃 函数的另一个版本,这个函数一个网址参数,没有指定返回值类型,并直接输出 String 值,而不是返回它:

func 网址(site: String) {
    print("米尔视觉创意:\(site)")
}
网址(site: "https://millva.com/APPS.html")

多重返回值函数

理解难度
★★★★☆
实用程度
★★☆☆☆

函数可以有不只一个的返回值,返回值超过一个时以一个元组(Tuple)返回,元组内包含着要回传的每个值的类型标注。在建立函数时也可以给返回元组的每个值加上名称。以下是一个例子:

// 定义函数 有一个类型为 Int 的参数, 返回两个类型为 Int 的值
func findNumbers(number: Int) -> (Int, Int) {
    let n = number + 10
    // 返回一个元组
    return (number, n)

    // 合并成一行直接返回也是可以
    // return (number, number + 10)
}

// 呼叫函数 传入整数 12 会返回 (12, 22)
let numbers = findNumbers(number: 12)
// numbers 为一个元组 可以自 0 开始算 依序取得其内的值
// 打印:12 and 22
print("\(numbers.0) and \(numbers.1)")


// 定义另一个函数 将上面函数中返回的元组内的值加上名称
func findNumbers2(number: Int) -> (oldNumber: Int, newNumber: Int) {
    let n = number + 10
    return (number, n)
}

// 呼叫函数 传入整数 24 会返回 (24, 34)
let numbers2 = findNumbers2(number: 24)
// 这边即可使用定义函数时 返回元组内的值设定的名称
// 打印:24 and 34
print("\(numbers2.oldNumber) and \(numbers2.newNumber)")

可选元组返回类型

理解难度
★★★★☆
实用程度
★★☆☆☆

如果整个返回的元组可能会没有值(nil),可以将此返回元组设为可选元组类型,使用方式为在括号()后面接着一个问号?,像是(Int, String)?或是(String, Int, Int)?。以下是个例子:

// 定义函数 参数为一个类型为 [Int] 的阵列
// 返回值为 包含两个类型为 Int 的元组 或是 nil
func findNumbers3(arr: [Int]) -> (Int, Int)? {
    // 检查传入的阵列 如果其内没有值的话 就直接返回 nil
    if arr.isEmpty {
        return nil
    }
    let n = arr[0] + 10
    let n2 = arr[0] + 100
    return (n, n2)
}

// 呼叫函数
// 因为返回的是一个可选类型 这边先做可选绑定的动作 确定有值后再打印来
if let numbers = findNumbers3(arr: [11,22,33]) {
    print("\(numbers.0) and \(numbers.1)")
}
// 如果传入的阵列 内部没有值
if let numbers = findNumbers3(arr: []) {
    print("这里不会被打印来 \(numbers.0)")
}

函数类型

理解难度
★★☆☆☆
实用程度
★★★★☆

函数也是一种类型,由函数的参数类型和返回值类型组成:

func someFunction(a: String, b: Int) -> Int {
    // 函数内部程式
}

上述程式中的函数,这个函数类型就标注为(String, Int) -> Int,意思就是有两个类型依序为String跟Int的参数,会返回一个类型为 Int 的值。

以下是另一个例子,如果没有参数也没有返回值时,函数类型标注为( ) -> Void。

func hello5() {
    print("Hello !")
}

这个函数类型也可以标注为() -> ()。实际上,没有返回值的函数,会返回一个特殊的值,叫做Void,也就是一个空的元组(tuple),没有任何元素,可以写成( )。

使用函数类型

理解难度
★★★★☆
实用程度
★☆☆☆☆

前面刚提过函数是一种类型,所以也可以将变数或常数声明为一个函数,然后可以指派一个适当的函数。

以下是一个例子,声明一个变数mathFunction,是一个类型为(Int) -> Int的函数,最后指派一个已经存在且类型相同的函数:

var mathFunction: (Int) -> Int = addTen

函数类型作为参数类型

理解难度
★★★★☆
实用程度
★☆☆☆☆

函数可以作为另一个函数的参数,以下是个例子:

// 定义一个将两个整数相加的函数
func addTwoInts(number1: Int, number2: Int) -> Int {
    return number1 + number2
}

// 定义另一个函数,有三个参数依序为
// 类型为 (Int, Int) -> Int 的函数, Int, Int
func printMathResult(
 _ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}

// 将一个函数 addTwoInts 传入函数 printMathResult
printMathResult(addTwoInts, 3, 5)

上述程式中,作为参数的函数只需要类型正确,不用了解其内的程式如何运作,这表示可以将 printMathResult 函数一部分的操作交给呼叫函数的人来实作,也是以一种类型安全(type-safe)的方式来保证传入函数的呼叫是正确的。

函数类型作为返回类型

理解难度
★★★☆☆
实用程度
★★★☆☆

函数可以作为另一个函数的返回值,使用方式为在返回箭头(->)后写一个完整的函数类型。

以下例子:

// 定义一个将传入的参数加一的函数
func stepForward(input: Int) -> Int {
    return input + 1
}

// 定义一个将传入的参数减一的函数
func stepBackward(input: Int) -> Int {
    return input - 1
}

// 建立一个参数为布林值的函数 会返回一个函数
// 根据布林值返回上述两个函数的其中一个
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
    return backwards ? stepBackward : stepForward
}

// 声明一个整数常数
let number = 3
// 声明一个函数常数
let someFunction2 = chooseStepFunction(backwards: number > 0)
// 根据 chooseStepFunction 函数的内容
// 传入 true 时 会返回 stepBackward 函数
// 所以 someFunction2 会被指派为 stepBackward

someFunction2(10) // 返回 9

这边声明函数常数时没有标注类型,因为就如同其他变数或常数声明时,Swift 会根据指派的函数自动判断出类型。

Swift基础入门知识学习(11)-闭包-第一篇-讲给你懂

超速学习-重点笔记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MillVA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值