Swift的函数和函数类型是非常重要的内容.
而且Swift中也把函数的形式和方法的形式,定义的完全一致;只不过,函数不是在类中.
1.函数的定义
func 函数名(参数列表) [ - > 返回值类型]
{
//函数体
}
解释:
func是关键字,是必须写上的前缀,代表它是一个函数或方法;
函数名 :遵从标识符的规则
形参列表,可以为空,也可以很多;例如 str:String,a:Int,和声明变量的方法类似
-> 后面跟的是返回值类型,如果函数的返回值为空,可以省略 -> 返回值类型
函数举例:
(1)定义一个有参数,有返回值的函数
func myFuncName(a:Int,b:String)->String { return b; }
(2)返回值为空的各种写法
func myFunc1(a:[Int])->Void { //参数为数组,返回值为空的函数 } func myFunc2(a:Int) { //返回值为空的函数,不写箭头和类型 } func myFun3(a:String)->() { //返回值为空的情况,使用括号 } func myFun4() { //没有参数,也没有返回值的函数 }
(3)返回参数是一个元组,即函数返回多个值的函数,这一点与C语言大有不同
//3.函数返回多个值的情况,即返回一个元组 func myFun5(arr:[Int])->(max:Int,min:Int)//注意,此处的返回元组类型的元组的变量名称不重要,但是类型要一致 { var Max=99 var Min=0 return (Max,Min) }
2.函数的调用,方式和C语言类似
直接使用函数名,加上参数即可调用
myFun3("测试") var str = myFun3("测试") myFun4()
对于有返回值的函数,可以使用一个变量来接收其值,
这种方式还可以用在Swift的函数重载中,根据返回值的不同来区分同名的函数
3.函数的外部形参名 与 #号
当你习惯了 Oc的方法调用时,你会发现 其 可读性非常好;原因是Oc的方法一般都会给参数起一个名字,你在调用时就会出现,以此就会给你一定的提示
如
[NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(setMath3) userInfo:nil repeats:YES];
每一参数的前面都有对应的名称,如 TimeInterval/ target /selector
但是在我们上面的函数调用时却没有让我们输入,该形参对应的名.
如何解决?
(1)只需在参数前加上一个标识符加以说明即可,这个标识符叫做外部形参名 ; 括号里的 height叫做局部形参名(外部调用时,不可见)
如下:
func myFun6(高 height:Int,宽 width:Int) { }
在参数的前面加上 高,宽 这两个外部形参名;
那么在调用的时候,就会自动保留该 高,宽,这两个外部形参名
//调用方法 myFun6(高: 22,宽: 31)
height 和 width是 内部/局部形参名,该形参名在外界调用时,不会显示
(2)当然,系统也提供了更简单的方法,就是让 外部形参名与 局部形参名保持相同即可
在形参名的前面加上 #号即可
//外部形参名,和局部形参名一样,前面加上#号 func myFun7(#height :Double,#width:Float) { }
调用时,系统自动帮我们加上,同局部形参名一样的名字
myFun7(height: 22,width: 33)
(3)让然,有时候我们 为了 省略 构造器中系统自动为我们加上的 外部形参名,则可以直接 使用 下划线,忽略即可
class A { var aa :String init(aa : String) { self.aa = aa } } var aa:A = A(aa: "构造器的")
可以发现,上面的代码,自动为我们加上了 外部形参名 aa
如果我们不需要的话,使用 下划线即可去掉
class A { var aa :String init(_ aa : String) { self.aa = aa } } var aa:A = A("构造器的")
可以看到 A("构造器") 该方法 没有 外部形参名了.
4.函数的形参默认值
我们可以给函数的参数设置对应的默认值,该参数最好放在 参数列表的最后
这样我们调用函数时就可以省略某些参数了.
func myFunc9(msg:String,name:String="默认字符串") { println(msg+"----"+name) } //系统自动给默认的局部参数名,加上一个外部形参名 myFunc9("你好",name: "哈哈") myFunc9("你好")
输出:
你好----哈哈 你好----默认字符串
可以看到,如果调用函数时,有默认值的参数缺失也是可以的,那么它将会以默认值来赋值;否则会覆盖掉默认值
5.个数可变的形参
Swift的函数的最后一个参数的个数,可以是变化的,这相当于传入了 一个数组参数
最后一个可变形参,需要使用3个点放在最后,代表可变
//个数可变的参数,此参数只能放在最后 func myFunc11(a:Int,books:String...) { for tmp in books { println(tmp+",") } }
6.形参的可变性
函数中的形参默认是 let 类型的,不可以变的;如果要 改变形参,需要手动使用 var 在 变量前说明
(1)不可变形参
//可变形参,值类型(默认是不可变的) func myFunc12(msg:Int) { //msg=22//如果参数之前不加上任何的参数,默认是Let类型的,不可以修改 }
上面的函数的参数 msg是 let常量类型的,不可以改变!
(2)可变形参
形参可变的函数,在参数前加 var
func myFunc13(var #msg:Int)//此var可变的参数,不会对实参(值类型)产生任何影响 { msg=22//参数之前加上var之后,可以修改 msg+=1 println(msg) }
7.如何直接修改实参本身? 使用Inout
对于函数来说,在默认情况下 在函数内部使用的是实参的副本;但很多时候,我们需要直接修改实参的值,这时,我们需要使用 inout 类型的形参;
并且在调用时使用 &实参 的形式来调用!
func myFunc14(inout a :Int,inout b:Int)//交换a,b { let tmp=a a=b b=tmp }
调用该函数:
var a1=33 var b1=44 println("交换之前a==\(a1),b==\(b1)") myFunc14(&a1,&b1) //调用时需要传入引用&,即可 println("交换之后a==\(a1),b==\(b1)")
输出:
交换之前a==33,b==44 交换之后a==44,b==33
对于引用参数,我们依然 可以使用上述方式,直接修改 实参的值
8.函数类型
函数类型实际上包含了函数的参数类型,返回值类型,不包括函数名,func;
通过函数类型,我们可以定义一个函数变量,这个函数变量对应的值就是函数的实现;一个 函数变量可以有多个实现;
然后我们通过函数变量就可以直接调用函数了
函数类型还可以作为闭包的类型.
示例;
(1)定义一个函数类型
var myFunction:(Int,String)->String
(2)函数类型相同的函数,两个以上
func myFunc1(#num:Int,word:String)->String { return String(num)+word } func myFunc2(num:Int,word:String)->String { return "测试"+String(num)+word }
(3)使用函数变量,多次接收函数类型一样的函数(名)
myFunction = myFunc1 var str=myFunction( 110,"你好!") println(str)
110你好!
myFunction = myFunc1 var str2 = myFunction(222,"第二个") println(str2)
输出:
222第二个
9.函数类型作为形参类型,即函数的参数可以是一个函数
使用函数类型作为参数的好处是在一个函数内部可以动态的执行不同的代码,我们只需要改变这个函数参数即可
示例:下面使用,两个函数类型一样的函数来作为另一个函数的参数
func myFunc1(#num:Int,word:String)->String { return "测试"+String(num)+word }
另一个函数,需要使用函数类型的参数,返回值是String类型
func fun2(var 字符串 str:String,函数参数 fun:(Int,String)->String)->String { var str2 = fun(001,str) println(str2) return str2; }
该func2是一个可以接受函数类型变量的函数,下面来给其函数参数传递不同的函数变量
fun2(字符串: "一个字符串",函数参数: myFunc1) fun2(字符串: "第二个函数",函数参数: myFunc2)
输出:
1一个字符串 测试1第二个函数
可以看到 函数 myFunc1,myFunc2都是作为一个参数传给 fun2,使其可以动态的执行函数体;这样做使得一个函数的功能可以更加强大,满足不同需求
10.函数类型也可以作为函数的返回值类型
一个函数,也可以返回一个函数变量,通过函数变量我们也可以调用这个函数!
两个被用作返回函数的函数
类型是 (Int,Int)->Int
功能是 加减法
func plus(a:Int,b:Int)->Int { println("a+b=\(a+b)") return a+b } func minus(a:Int,b:Int)->Int { println("a-b=\(a-b)") return a-b; }
返回值类型为函数类型的函数
func fun3(a:Int,b:Int)->(Int,Int)->Int { if a>b { return plus //返回一个函数 } else { return minus } }
可以简单的理解为 func3函数返回了一个函数,或者一段代码;这个返回的函数需要用一个变量来接收
var a = 10 var b = 9 //用一个变量来接受这个返回的函数类型的变量 var funcV = fun3(a,b) funcV(9,8)
fun3此时返回 plus函数
输出:
a+b=17
var a1 = 2 var b1 = 3 var funV2 = fun3(a1,b1) funV2(1,8)
fun3返回 minus函数
var a1 = 2 var b1 = 3 var funV2 = fun3(a1,8)
输出:
a-b=-7
11.函数的嵌套
函数是可以嵌套函数的,如果你要使用函数内部的函数,那么你需要 返回一个 函数类型
方法和上面类似,只需把plus minus两个函数放到其他函数内部定义即可
把其他的函数,放在一个函数内,并且返回值为对应的内部函数类型;
那么我们也可以在外部通过调用外部函数,从而得到函数的返回值,从而可以使用内部的函数了
func fun3(a:Int,Int)->Int { func plus(a:Int,b:Int)->Int { println("a+b=\(a+b)") return a+b } func minus(a:Int,b:Int)->Int { println("a-b=\(a-b)") return a-b; } if a>b { return plus //返回一个函数 } else { return minus } }
使用方法和 10完全类似
var a = 10 var b = 9 //用一个变量来接受这个返回的函数类型的变量 var funcV = fun3(a,8) var a1 = 2 var b1 = 3 var funV2 = fun3(a1,8)
输出:
a+b=17 a-b=-7
12.函数的重载
函数的重载,就是一个函数的名称相同,但是 参数或者返回值类型不同
但这对Swift来说还不全对,因为 Swift的外部形参名也可以用来区分你调用是哪个函数,也可用于函数重载,即使参数,返回值类型完全一致
(1)一个普通的加法函数
func plus(a:Int,b:Int)->Int { return a+b }
调用方式,因为存在返回值类型不同的重载函数,所以我们必须用一个类型确定的变量来接收返回值
如何调用?
var p:Int = plus(2,2)
(2)参数个数不同
func plus(a:Int)->Int { return a }
此重载类型有时候可以省略,用一个返回值来接收的步骤(除非也有返回类型与其不同的函数)
调用方式2种
plus(2) var p = plus(2)
(3)参数类型不同
func plus(a:Int,b:String)->Int { return a }
调用方式:
plus(2,"参数类型不同") var p = plus(2,"参数类型不同")
(4)返回值类型不同
func plus(a:Int,b:Int)->String { return String(a+b) }
必须确定返回值类型:
var str:String = plus(1,2)
(5)外部形参名不同(其他都相同)
func plus(#a:Int,第二个数 b:Int)->Int { return a+b }
调用方式,2种:
plus(a: 22,第二个数: 33) var pp = plus(a: 22,第二个数: 33)
(6)参数类型,外部形参名,返回值类型都不同
func plus(#a:Int,第二个 b:String )->String { return "\(a)"+b }
调用方式2种
plus(a:33,第二个:"ww") var str2:String = plus(a:33,第二个:"ww")
13.函数与方法
方法的定义形式写法与函数是完全一致的,只不过方法定义的位置是在 类,结构体,枚举中.
Swift教程大全:http://blog.csdn.net/yangbingbinga