swift 笔记 (六) —— 函数

来源:互联网 发布:shop域名注册 编辑:程序博客网 时间:2024/05/30 23:20
函数
在Swift中,每个函数都可以被当做一个类型使用,也就是说,可以把函数当作另一个函数的参数,当作另一个函数的返回值,用来定义变量等等。其实很多语言都可以这么干。

函数的原型:
func 函数名(参数名: 参数类型) -> 返回值类型 {     //多个参数用”,”分隔
     函数体
}
当然,函数的基本原型是这样的,还有很多变种,后面会一一提到
最开始看到->这个符号的时候,还吐槽了好一会,现在看来就顺眼多了,更清晰的为“返回值”这一抽象概念做了相对形象的表达。

func myFunc(someBody: String, saySomething: String) -> String{
     return someBody + “ say: “ + saySomething
}

println(myFunc(“kitty”, “hello!”))

无参的函数,就直接留个()在那里,不需要写别的:
func 函数名() -> 返回值类型 { 函数体 }

无返回值的函数, ->以及后面的类型都省略:
func 函数名(参数名: 参数类型) {函数体)            //在文档中描述说,无返回值的函数,其实它还是返回了东西,类型为void

当然,即使定义了一个返回值类型的函数在被调用的时候,如果你不需要,完全可以忽略他的返回值,但建议如果是不需要关心返回值的函数,直接在原型上定义为无返回值的函数,既然已经定义了返回值的,那么还是要关心一下的,并且在函数调用结束后对其检查,避免一些奇怪的bug出现。

多返回值函数,这种需求其实非常早就有,只不过早期的语言,受数学的函数影响太大“一个函数在给定一个参数的时候,只有一个明确的返回值”(我猜的。。。。),先来看看多返回值的函数在swift中的原型:
func 函数名(参数列表) -> (返回值1名: 返回值1类型, 返回值2名: 返回值2类型) {     //这里的返回值是个元组(tuple)
     函数体

func myCompare(firstNum: Int, secondNum: Int) -> (bigger: Int, smaller: Int){
     if firstNum >= secondNum {
          return (firstNum, secondNum)
     } else {
          return (secondNum, firstNum)
     }
}

let myRet = myCompare(5, 3)
println(myRet.bigger)
println(myRet.smaller)

当然也可以定义一个不指定返回值名字的函数:
func 函数名(参数列表) -> (返回值1类型,  返回值2类型) {
     函数体
}

func myCompare(firstNum: Int, secondNum: Int) -> (Int, Int){
     if firstNum >= secondNum {
          return (firstNum, secondNum)
     } else {
          return (secondNum, firstNum)
     }
}

let myRet = myCompare(5, 3)
println(myRet.0)          //因为没有定义返回值的名字,所以这里要用.0使用第一个参数
println(myRet.1)          //因为没有定义返回值的名字,所以这里要用.1使用第二个参数

External Parameter Names (外部使用的参数名,也就是在调用函数的时候使用的参数名)
func myFunc(strParam str: String) -> String {     //在原本参数前面加一个名字和空格
     return "hello “ + str     //str是在函数体内部使用的参数名
}

println(myFunc(strParam: “kitty”)     //因为在函数定义的时候指定了一个external parameter name,所以在调用这个函数的时候,必须写出这个名字

如果不想费事,或者是找不到一个更适合描述这个参数的名字的时候,需要让外部调用和函数体内部都使用同样的参数名的时候,可以使用#来达到这个目的

func myFunc(#strParam: String) -> String {
     return “hello “ + strParam    
}

println(myFunc(strParam: “world”))

参数的默认值
要注意的是,带默认值的参数,必须在函数的参数列表的最后面,也就是说,当指定一个有默认值的参数的时候,这个参数的后面的所有参数都必须有默认值,或者它就是最后一个参数 (可是我在xcode里测试的时候发现,放在前面也没事。。。不知道是不是个bug,但既然文档这样描述,我们还是要按着规则来,万一哪一天Xcode改了策略。。。。)

func myJoin(string1: String, string2:String, withJoiner joiner: String = “ “) -> String {
     return string1 + joiner + string2
}

println(myJoin(“hello”, “world”)
println(myJoin(“hello”, “world”, withJoiner: “ ^_^ “)

变长参数
和C里类似,使用…(三个点)表示,一个函数最多只能有一个变长的参数,而且又是必须放在参数列表的最后面
不多说,直接上官方的例子:


有时候,我们希望可以把传入的参数当做一个函数体内部的变量:
func myFunc(myParam: Int) {
     var param = myParam
     while param > 0 {
          xxx
          --param
     }
}
现在Swift帮我们简单了这个操作:
func myFunc(var myParam: Int) {
     while myParam > 0 {
          xxx
          --param(感谢 swift技术交流第一平台(355277)的群友 偏未晚(1027115179)  指出参数的笔误)
          --myParam
     }
}

In-Out参数
当然有时候我们希望这个参数是可以改完之后,返馈在函数外面原本定义的变量的时候可以使用In-Out参数:

var myArray = [1, 2, 3]
func myFunc(inout ary: Array<Int>) {          //在参数前面使用 inout 关键字表明,ary这个参数是In-Out的
     ary[1] = 8
}

myFunc(&myArray)          //在传入的参数前面加一个 & 符号表示这个参数是In-Out,他可能在函数内部被改变

函数的类型
最开始的时候,有提到,每个函数都有一个类型,这个类型使我们可以把函数当作参数,也可以当作返回值,等等。

func myFunc(intputString: String) -> String {
     return inputString
}     //这个函数标红,下面要用到
这个函数除了把参数返回之外,没干别的,当然,他也有自己的类型:
(String)-> String     //这个类型的函数,他有一个String类型的参数,并且返回了一个String类型的值

如果我们想把函数当作参数传入另一个函数,至少也要给他个名字吧,不然怎么在另一个函数里使用:
var myFuncType: (String) -> String     //为 (String)->String 这个函数类型,定义了一个引用,叫myFuncType
myFuncType = myFunc          //为引用赋值为 myFunc, 刚刚上面有这个函数的定义
func myFuncFunc(localFunc: myFuncType) {       //myFuncType在这里可以像 String, Int, Double等类型一样用
     localFunc(“hello”)          //localFunc的定义此时就与myFuncType一样,而且它就是myFunc的引用
}

println(myFuncFunc(“hello”)  //这句输出为 “hello”, 因为myFunc的行为如此,myFuncFunc里面也没有做多余的操作

当然,不提前定义myFuncType也是可以的,直接把函数的类型写在参数里:
func myFuncFunc(localFunc: (String) -> String) {…}

调用的时候就要把函数名传进去了:
myFuncFunc(myFunc)

我们还可以把函数做为返回值
其实跟上面的大同小异了:

func myNewFunc() -> (String) -> String {
     return myFunc               //myFunc的定义在上面
}

let myTempFunc = myNewFunc()
myTempFunc(“hello”)           //此函数的行为与 myFunc一样 

当然,也可以这么写:
myNewFunc()(“hello”)          //和上一句的结果是一样的

嵌套函数
func myNewFunc() -> (String) -> String {
     func retTheString(str: String) -> String {          //不要纠结str从哪来的,因为外层函数并不使用这个函数,它只是个定义
          return str
     }

     return retTheString          //刚刚定义的 retTheString作为返回值,传给myNewFunc的外部使用
}

let myTempFunc = myNewFunc()     //此时 myTempFunc拥有了和 retTheString一样的行为 
myTempFunc(“Hello”)                       //这个”hello”才是上面提到的那个str, 好了现在可以纠结str从哪来的了

0 0
原创粉丝点击