2.5 swift函数的类型
我们之前把函数看做是代码的逻辑单元,实际上不仅如此,函数还和我们用var或let定义的东西一样,可以被赋值并且有类型呢!怎么样?是不是感觉函数这家伙看似忠厚老实,其实背后还有故事?确实,函数背后面还有大大的故事呢。
1、函数是个什么
func printStr(str: String) {
print(str)
}
let anotherPrintStr = printStr
anotherPrintStr("Hello world") // 在控制台输出 "Hello world"
我们首先定义了一个函数 printStr 接着我们把它赋值给了一个用let声明的常量 anotherPrintStr,然后,然后,然后 anotherPrintStr 居然可以被当做一个函数进行调用了。这篇代码看起来还是不够明显,让我们继续研究一下,我们应该还记得我们之前提前过的 类型推断 机制吧,既然swift是一们静态的强类型语言,那么它是不会允许常量 anotherPrintStr 没有类型而存在,此时一定是类型推断机制在暗中给 anotherPrintStr 赋予了类型,我们可以通过xcode帮助我们揪出这个类型是什么,这个类型就是: (String) -> Void
函数的类型是由 参数类型与返回值类型共同决定的,Void代表函数没有返回值,如果一个函数既没有参数也没有返回值,那么该函数的类型应该是 () -> Void
那么也就是说我们可以用显示声明的方式来定义anotherPrintStr了。
let anotherPrintStr: (String) -> Void = printStr
anotherPrintStr("Hello world") // 在控制台输出 "Hello world"
这个时候我们已经完全明白anotherPrintStr不过是一个函数类型的常量吗,但是函数printStr到底是什么呢?我们尝试用函数类型重新定义一下printStr。
let printStr: (String) -> Void = {str in
print(str)
}
printStr("Hello world") // 在控制台输出 "Hello world"
通过这段代码我们可以这样理解printStr,它是一个用let声明的常量,类型是函数类型 (String) -> Void 它的值是一段可以执行的代码体(这是闭包的定义方式,我们可以暂时忽略)。也就是说和一个整形常量的区别在于,printStr的值可以被执行。
2、函数是一类公民
我们可能早就听说了,swift的函数是一类公民,这其实说的是函数与swift的其他类型一样,并没有受到歧视,而是得到了平等的对待,这包括赋值,传递,作为参数和返回值等。
func printStr(str: String) {
print(str)
}
func anewFunc(perform: (String) -> Void) -> (String) -> Void {
return perform
}
anewFunc(printStr)
我们定义了一个函数 anewFunc 它接收一个 (String) -> Void 类型,并返回一个 (String) -> Void 类型。我们可以把函数作为参数传递给 anewFunc ,而该函数又将其做为返回值。
3、这一切都是为了啥
我们现在承认 函数确实能做为另外一个函数的参数和返回值,可是这折腾来折腾去的是为了啥呢?我想这应该有两点原因。
-
写代码的一个重要目标是提高代码的复用度,这同时也能标识一个程序员水平的高低,编程语言提供的抽象表达能力,以及我们经常讨论的各种设计模式都是在为了实现这一目标,如果函数能够成为一等公民,那么意味着我们将获得一种将模板与代码行为分离的表达能力,这是一种很强的抽象表达能力,可以有效的提高代码的复用度可以看另外一篇内容来介绍闭包)。
-
所有我们声明的内容,都有其作用域和声明周期,如果我们想打破其作用域和声明周期,那么我们可以使用return语句或者是闭包(可以看另外一篇内容来介绍swift的作用域)。