经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » iOS » 查看文章
Swift系列三 - 函数
来源:cnblogs  作者:1024星球  时间:2021/5/7 11:49:39  对本文有异议

函数在任何语言中都是存在的,Swift中函数更加灵活。

一、函数的定义

1.1. 有返回值(形参默认是let,也只能是let)

  1. func pi() -> Double {
  2. return 3.14
  3. }
  4. print(pi()) // 输出:3.14
  5. func sum(v1: Int, v2: Int) -> Int {
  6. return v1 + v2
  7. }
  8. print(sum(v1: 10, v2: 20)) // 输出:30

1.2. 无返回值

  1. func hello() -> Void {
  2. print("hello")
  3. }
  4. func hello() -> () {
  5. print("hello")
  6. }
  7. func hello() {
  8. print("hello")
  9. }
  10. hello() // 输出:hello

1.3. 如果整个函数体是一个单一表达式,那么函数会隐式返回这个表达式

  1. func sum(v1: Int, v2: Int) -> Int {
  2. v1 + v2
  3. }
  4. print(sum(v1: 10, v2: 10)) // 输出:20

1.4. 返回元组:实现多返回值

  1. func calculate(v1: Int, v2: Int) -> (sum: Int, difference: Int, average: Int) {
  2. let sum = v1 + v2
  3. return (sum, v1 - v2, sum >> 1)
  4. }
  5. let result = calculate(v1: 10, v2: 20)
  6. print(result.sum, result.difference, result.average) // 输出:30 -10 15

1.5. 参数标签

函数可以修改参数标签:

  1. // at是外面调用的,time是函数内部使用的
  2. func goToWord(at time: String) {
  3. print("time is \(time)")
  4. }
  5. goToWord(at: "8:00")

可以使用下划线_省略参数标签:

  1. func sum(_ v1: Int, _ v2: Int) -> Int { v1 + v2}
  2. sum(10, 20)

1.6. 默认参数值

  • 参数可以有默认值
  1. func check(name: String = "nobody", age: Int, job: String = "none") {
  2. print("name=\(name), age=\(age), job=\(job)")
  3. }
  4. check(age: 10)
  5. check(name: "Jack", age: 20, job: "Programmer")
  6. check(name: "Eve", age: 18)
  7. check(age: 10, job: "Superman")
  8. /*
  9. 输出:
  10. name=nobody, age=10, job=none
  11. name=Jack, age=20, job=Programmer
  12. name=Eve, age=18, job=none
  13. name=nobody, age=10, job=Superman
  14. */
  • C++的默认参数有个限制:必须从右往左设置,而且不能跨标签;Swift拥有参数标签,因此没有此类限制
  • 省略参数标签时,需要特别注意,避免出错
  • 没有默认值的参数标签不能省略(如上面代码age就不能省略)

1.7. 可变参数

  • 一个函数最多只能有1个可变参数
  1. func sum(_ numbers: Int...) -> Int {
  2. var total = 0
  3. for number in numbers {
  4. total += number
  5. }
  6. return total
  7. }
  8. let result = sum(10, 20, 30, 40)
  9. print(result) // 输出:100
  • 紧跟在可变参数后面的参数不能省略参数标签(思考:如果省略了会怎么样?)
  1. func test(_ numbers: Int..., string: String, _ other: String) {
  2. }
  3. test(10, 20, 30, string: "idbeny", "1024星球")

1.8. 输入输出参数

  • 可以用inout定义一个输入输出参数:可以在函数内部修改外部实参的值
  • inout必须和&配合使用
  • 本质上是地址传递
  • 可变参数不能标记为inout
  • inout参数不能有默认值
  • inout参数只能传入可以被多次赋值的

如下修改会报错(因为形参是用let修饰的)

使用inout&

  1. var number = 10
  2. func add(_ num: inout Int) {
  3. num = 20
  4. }
  5. add(&number)
  6. print(number) // 输出:20

通过这种方式也可以交换两个变量的值(其实官方有提供交换函数swap

  1. // 方法一(使用临时变量)
  2. func swapValues(_ v1: inout Int, _ v2: inout Int) {
  3. let temp = v1
  4. v1 = v2
  5. v2 = temp
  6. }
  7. var num1 = 10
  8. var num2 = 20
  9. swapValues(&num1, &num2)
  10. print("num1=\(num1), num2=\(num2)") // 输出:num1=20, num2=10
  11. // 方法二(使用元组)
  12. var num3 = 30
  13. var num4 = 40
  14. func swapValues1(_ v1: inout Int, _ v2: inout Int) {
  15. (v1, v2) = (v2, v1)
  16. }
  17. swap(&num3, &num4)
  18. print("num3=\(num3), num4=\(num4)") // 输出:num3=40, num4=30
  19. // 方法三(系统提供的swap函数)
  20. var num5 = 50
  21. var num6 = 60
  22. swap(&num5, &num6)
  23. print("num5=\(num5), num6=\(num6)") // 输出:num5=60, num6=50

二、函数的文档注释

官网介绍:https://swift.org/documentatior/api-design-guidelines

光标放到对应函数名称上,按下Option即可查看函数相关描述文档

  • 上图看到sum的函数描述都是空的,如何填写描述信息呢?
  • 添加文档快捷键(光标一定要在函数上或函数上方):Command + Option + /

默认的文档注释

  1. /// <#Description#>
  2. /// - Parameters:
  3. /// - v1: <#v1 description#>
  4. /// - v2: <#v2 description#>
  5. /// - Returns: <#description#>
  6. func sum(v1: Int, v2: Int) -> Int { v1 + v2}

更详细的文档注释(概述和详述一定要隔开,否则会默认为详述)

  1. /// 将2个整数相加【概述】
  2. ///
  3. /// 将2个整数相加【详细的描述】
  4. /// - Parameters:
  5. /// - v1: 第一个参数
  6. /// - v2: 第二个参数
  7. /// - Returns: 2个参数的和
  8. /// - Note:传入2个整数【批注】
  9. func sum(v1: Int, v2: Int) -> Int { v1 + v2}

效果

三、函数重载

  • OC是不支持函数重载的,但Swift支持函数重载
  • 规则
    • 函数名相同
    • 参数个数不同 || 参数类型不同 || 参数标签不同

以下函数都构成了函数重载,都是可以正常调用的,且函数没有冲突:

  1. // 参照
  2. func sum(v1: Int, v2: Int) {
  3. v1 + v2
  4. }
  5. // 参数个数不同
  6. func sum(v1: Int, v2: Int, v3: Int) {
  7. v1 + v2 + v3
  8. }
  9. // 参数类型不同
  10. func sum(v1: Int, v2: Double) {
  11. Double(v1) + v2
  12. }
  13. // 参数标签不同(忽略标签)
  14. func sum(_ v1: Int, _ v2: Int) {
  15. v1 + v2
  16. }
  17. // 参数标签不同(标签名不同)
  18. func sum(a: Int, b: Int) {
  19. a + b
  20. }
  • 返回值类型与函数重载无关

  • 默认参数值和函数重载一起使用产生二义性时,编译器不会报错(在C++中会报错)

  1. func sum(v1: Int, v2: Int) -> Int {
  2. v1 + v2
  3. }
  4. func sum(v1: Int, v2: Int, v3: Int = 30) -> Int {
  5. v1 + v2 + v3
  6. }
  7. sum(v1: 10, v2: 20) // 输出:30
  • 可变参数、省略参数标签,函数重载一起使用产生二义性时,编译器有可能会报错

为什么是可能会报错?(下面代码可以正常执行,所以平时开发中也不建议这样写)

  1. func sum(_ v1: Int, _ v2: Int) -> Int {
  2. v1 + v2
  3. }
  4. func sum(_ numbers: Int...) -> Int {
  5. var total = 0
  6. for num in numbers {
  7. total += num
  8. }
  9. return total
  10. }
  11. sum(10, 20) // 输出:30

四、函数类型

每一个函数都是有类型的,函数类型由形式参数类型,返回值类型组成:

  • 函数类型可以作为函数参数传递;
  • 函数类型可以作为函数返回值;
  • 返回值是函数类型的函数,叫做高阶函数

五、嵌套函数

将函数定义在函数内部:

  1. func foward(_ forward: Bool) -> (Int) -> Int {
  2. func next(_ input: Int) -> Int {
  3. input + 1
  4. }
  5. func previous(_ input: Int) -> Int {
  6. input - 1
  7. }
  8. return forward ? next : previous
  9. }
  10. foward(true)(1) // 输出:2
  11. foward(false)(2) // 输出:1

六、内联函数

如果开启了编译器优化(Release模式默认开启),编译器会自动将某些函数变成内联函数:

  • Release默认按照快速运行方式优化;
  • Debug也可以手动开启,但是为了开发中方便调试,一般都会关闭。

内联函数的作用?

  • 内联函数在C++中的经常出现,如果某一个函数是内联函数,编译器在编译的时候会把适当的代码块中的代码放到对应位置,提高代码执行的效率
  • 将函数调用展开成函数体
  1. func test() {
  2. print("test")
  3. }
  4. test()
  • 以上代码如果开启编译器优化,test()会替换为print("test")

不是所有的内联函数都会被编译器展开函数体,那些函数不会被内联?

  • 函数体比较长
  • 包含递归调用
  • 包含动态派发

@inline
永远不会被内联(即使开启了编译器优化)

  1. @inline(never) func test() {
  2. print("test")
  3. }

开启编译器优化后,及时代码很长,也会被内联(递归调用、动态派发的函数除外):

  1. @inline(__always) func test1() {
  2. print("test")
  3. }
  • 在Release模式下,编译器已经开启优化,会自动决定哪些函数需要内联,因此没必要使用@inline

更多系列文章,请关注 微信公众号【1024星球】

原文链接:http://www.cnblogs.com/idbeny/p/swift-syntax-function.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号