04-函数

2020-10-20  本文已影响0人  bytebytebyte
//函数1-22
//1.函数的定义,形参默认是let 也只能是let,let省略了
func pi() -> Double {
    return 3.14
}
pi()

func sum0(v1: Int, v2: Int) -> Int {
    return v1 + v2
}
print(sum0(v1:1,v2:2))

//2. 3个无返回值等价 Void就是空元组
public typealias Void = ()
func sayHello0() -> Void {
    print("Hello0")
}
func sayHello1() -> () {
    print("Hello1")
}
func sayHello2() {
    print("Hello2")
}
sayHello0()
sayHello1()
sayHello2()

//2.隐式返回:如果函数体是一个单一的表达式,那么函数会隐式返回这个表达式
func sum1(v1: Int, v2: Int) -> Int {
    v1 + v2
}
print(sum1(v1: 10, v2: 20))

//3.返回元组:实现多返回值
func calculate(v1: Int, v2: Int) -> (sum2: Int, difference: Int, average: Int) {
    let sum2 = v1 + v2
    return (sum2, v1 - v2, sum2 >> 1) //结合10进制理解这个移位 2进制右移一位相当于十进制除以2
}
let result = calculate(v1: 20, v2: 10)
result.sum2
result.difference
result.average

//4.函数的文档注释

///  求和【概述】
///
/// 将2个整数相加【更详细的描述】
///
/// - Parameter v1:第1个参数
/// - Parameter v2:第2个参数
/// - Returns:2个整数的和
///
/// - Note:传入2个整数即可【批注】
///
func sum3(v1: Int, v2: Int) -> Int {
    v1 + v2
}

sum3(v1: 1, v2: 2)

//5.参数标签
//可以修改参数标签 time在内用 at在外用
func goToWork(at time: String) {
    print("this time is \(time)")
}
goToWork(at: "08:00") //为什么这么设计?更像个句子好理解

func goToWork(time: String) {
    print("this time is \(time)")
}
goToWork(time: "08:00")//this time is 08:00

//6.可以使用下划线省略_ 省略参数标签,尽量少用,多用上边,易读
func sum4(_ v1: Int, _ v2: Int) -> Int {
    v1 + v2
}
sum4(10,20)

//7.默认参数值
//参数可以有默认值
func check(name: String = "nobbody", age: Int, job: String = "none") {
    print("name = \(name), age = \(age), job = \(job)")
}
check(name: "Jack", age: 20, job: "Doctor")//name = Jack, age = 20, job = Doctor
check(name: "Rose", age: 18)//name = Rose, age = 18, job = none
check(age: 10, job: "aaa")//name = nobbody, age = 10, job = aaa
check(age: 15)//name = nobbody, age = 15, job = none
//C++的默认参数值有个限制:必须从右往左设置。由于swift拥有参数标签,因此并没有此类限制,但是在省略参数标签时特别注意,避免出错
//这里的middle参数不可省略参数标签
func test(_ first: Int = 10, middle: Int, _ last: Int = 30) {}
test(middle:20)


//8.可变参数,一个函数最多只能有一个可变参数
func sum5(_ numbers: Int...) -> Int {
    var total = 0
    for number in numbers {
        total += number
    }
    return total
}
sum5(10, 20, 30, 40)//100

//9.Swift自带的print函数
print("1","2","3",separator:"",terminator:"")
print(20)//12320

//10.紧跟在可变参数后面的参数不能省略参数标签 参数 string 不能省略标签,为什么?string: String如果是string: Int就分辨不清了怎么传值了
func test0(_ numbers: Int..., string: String, _ other: String) {}
test0(10, 20, 30, string: "Jack", "Rose")

//11.输入输出参数:可以用inout定义一个输入输出参数:可以在函数内部修改外部实参的值
//可变参数不能标记为inout,
//inout 参数不能有默认值,
//inout参数只能传入被多次赋值的,变量,数组元素
var numbers0 = [10, 20, 30]
numbers0[0] = 20
numbers0[0] = 30
func test1(_ num: inout Int) {
    
}
test1(&numbers0[0])
print(numbers0)

//12.inout参数的本质设计地址传递(引用传递)//汇编看出来的 lea是地址传递
func swapValues0(_ v1: inout Int, _ v2: inout Int) {
    let tmp = v1
    v1 = v2
    v2 = tmp
}
var num1 = 10
var num2 = 20
swapValues0(&num1, &num2)

func swapValues1(_ v1: inout Int, _ v2: inout Int) {
    (v1, v2) = (v2, v1)
}

swap(&num1, &num2)

//13.修改外部变量的值
var number0 = 10
func add(_ num: inout Int) {
    num = 20
}
add(&number0)//20

//14.函数重载
//函数名相同,参数个数不同||参数类型不同||参数标签不同
func sum6(v1: Int, v2: Int) -> Int {
    v1 + v2
}
//参数个数不同
func sum6(v1: Int, v2: Int, v3: Int) -> Int {
    v1 + v2 + v3;
}
//参数类型不同
func sum6(v1: Int, v2: Double) -> Double {
    Double(v1) + v2
}
//参数标签不同
func sum6(_ v1: Int, _ v2: Int) -> Int {
    v1 + v2
}
//参数标签不同
func sum6(a: Int, b: Int) -> Int {
    a + b
}
sum6(v1: 10, v2: 20)
sum6(v1: 10, v2: 20, v3: 30)
sum6(v1: 10, v2:20.0)
sum6(10, 20)
sum6(a: 10, b: 20)
//15.函数重载注意点
//1函数返回值类型与函数重载无关
func sum7(v1: Int, v2: Int) -> Int { v1 + v2 }
func sum7(v1: Int, v2: Int) {}
//sum7(v1: 10, v2: 20)//报错

//2默认参数值和函数重载一起使用产生二义性时,编译器并不会报错(在C++中会报错)
func sum8(v1: Int, v2: Int) -> Int {
    v1 + v2
}
func sum8(v1: Int, v2: Int, v3: Int = 10) -> Int {
    v1 + v2 + v3
}
sum8(v1: 10, v2: 20)//会调用sum8(v1: Int, v2: Int)
//3可变参数、省略参数标签、函数重载三者一起使用产生二义性时,编译器有可能会报错
//func sum9(v1: Int, v2: Int) -> Int {
//    v1 + v2
//}
//func sum9(_ v1: Int, _ v2: Int) -> Int {
//    v1 + v2
//}
//func sum9 (_ numbers: Int...) -> Int {
//    var total = 0
//    for number in numbers {
//        total += number
//    }
//    return total
//}
//sum9(10, 20)

/*
 16.内联函数
 如果开启了编译器优化,release模式默认会开启优化,编译器会自动将某些函数变成内联函数,将函数调用展开成函数体. Build Setting -> optimization
 哪些函数不会被自动内联?
 1.函数体比较长 2.包含递归调用 3.包含动态派发

 
 */

//理解函数内联
func test2() {
    print()
}

test2()//函数内联后这句实际是print(),少了函数调用压栈出栈等操作直接把函数体放在了这里
//理解动态派发
class Person {
    func test3() {
    }
}
class Student: Person {
    override func test3() {
    }
}
class Teacher: Person {
    override func test3() {
    }
}

var p : Person = Student()
p = Teacher()
p.test3() //编译器无法决定调用哪个函数

//在release模式下,编译器已经开启优化,会自动决定哪些函数需要内联,因此没必要使用@inline
//永远不会被内联,即使开启了编译器优化
@inline(never) func test4() {
    print("test4")
}
//开启编译器优化,即使代码很长,也会被内联(递归调用函数、动态派发的函数除外)
@inline(__always) func test5() {
print("test5")

//17.函数类型
//每一个函数都是有类型的,函数类型由形式参数类型、返回值类型组成
func test4() {}// () -> Void 或者 () -> ()
func sum10(a: Int, b: Int) -> Int { // (Int, Int) -> Int
    a + b
}
//18.函数类型定义变量
var fn: (Int, Int) -> Int = sum10 //调用时不需要参数标签

//19.函数类型作为函数参数
func sum11(v1: Int, v2: Int) -> Int {
    v1 + v2
}
func difference0(v1: Int, v2: Int) -> Int {
    v1 - v2
}
func printResult(_ mathFn: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFn(a,b))")
}
printResult(sum11, 5, 2) //Result: 7
printResult(difference0, 5, 2) //Result: 3

//20.高阶函数:返回值是函数类型的函数
func next(_ input: Int) -> Int {
    input + 1
}
func previous(_ input: Int) -> Int {
    input - 1
}
func forward(_ forward: Bool) -> (Int) -> Int {//(Int) -> Int返回值类型
    forward ? next : previous
}
forward(true)(3) //4
forward(false)(3) //2

//21.typealias 用来给类型起别名
typealias Byte = Int8
//元组
typealias Date = (year: Int, moth: Int, day: Int)
func test5(_ date: Date) {
    print(date.0)
    print(date.year)
}
test5((2011, 9, 10))

typealias IntFn = (Int, Int) -> Int
func difference1(v1: Int, v2: Int) -> Int {
    v1 - v2
}
let fn1: IntFn = difference1
fn1(20, 10)
func setFn(_ fn1: IntFn) {}
setFn(difference1)
func getFn() -> IntFn {difference1}

//22.函数嵌套:将函数定义在函数内部,不想让外部调用到
func forward0(_ forward0: Bool) -> (Int) -> Int {
    func next(_ input: Int) -> Int {
        input + 1
    }
    func previous(_ input: Int) -> Int {
        input - 1
    }
    return forward0 ? next : previous
}
forward0(true)(3) //4
forward0(false)(3) //2
}
上一篇下一篇

猜你喜欢

热点阅读