函数的定义
- 有返回值
func pi() -> Double{
return 3.14
}
func sum(v1:Int,v2:Int) -> Int{
return v1+v2
}
sum(v1: 10, v2: 20)
- 形参默认是
let
,也只能是let
- 无返回值
无返回值第一种写法
func sayHello() -> Void{
print("Hello")
}
无返回值第二种写法
func sayHello() -> (){
print("Hello")
}//返回值只有一个空的小括号(),可以认为是空元组
无返回值第三种写法
func sayHello() {
print("Hello")
}
隐式返回
- 如果整个函数体是一个单一表达式,那么函数会隐式返回这个表达式
func sum(v1:Int,v2:Int) -> Int{
v1+v2
}
sum(v1: 10, v2: 20)//30,如果花括号体里还有其他代码,则需要写return
返回元组:实现多返回值
func calculate(v1:Int,v2:Int) -> (sum:Int,difference:Int,average:Int){
//和 差 平均值
let sum = v1+v2
return (sum,v1-v2,sum>>1)
}
let result = calculate(v1: 20, v2: 10)
result.sum//30
result.difference//10
result.average//15
函数的文档注释
///求和【概述】
///
///将两个整数相加【更详细的描述】
///
/// - Parameter v1:第一个整数
/// - Parameter v2:第二个整数
/// - Returns:2个整数的和
/// - Note:传入2个整数即可【批注】
///
func sum (v1:Int,v2:Int)->Int{
v1+v2
}
- 注释参考如下文档
api设计准则
参数标签
- 可以修改参数标签
func goToWork(at time:String){
print("this is \(time)")
}
goToWork(at: "08:00")//this is 08:00
//at用在外边调用的时候,方便理解的词汇,time用在函数体里面,方便传参数的理解
- 可以使用下划线
_
省略参数标签,方便可读性几更新迭代,不建议省略
func sum(_ v1:Int,_ v2:Int) -> Int{
v1+v2
}
sum(20, 10)
默认参数值
- 参数可以有默认值
func check(name:String = "nobody",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: "Batman")
//name = nobody,age = 10,job = Batman
check(age: 15)
//name = nobody,age = 15,job = none
- c++的默认参数值有个限制:必须从右往左设置。由于swift拥有参数标签,因此并没有此类限制
- 但是在省略参数标签时,需要特别注意,避免出错
//这里的middle不可以省略参数标签
func test(_ first:Int = 10,middle:Int,_ last:Int = 30){}
test(middle: 20)
可变参数
func sum(_ numbers:Int...) -> Int {
var total = 0
for number in numbers {
total += number
}
return total
}
sum(10,20,30,40)
- 一个函数最多只能有1个可变参数
- 紧跟在可变参数后面的参数不能省略参数标签
func sum(_ numbers:Int...,str:String,_ other:String) -> Int {
var total = 0
for number in numbers {
total += number
}
return total
}
sum(10,20,30,40,str:"aaa","bbb")
swift自带的print
函数
/// - Parameters:
/// - items: Zero or more items to print.
/// - separator: A string to print between each item. The default is a single
/// space (`" "`).
/// - terminator: The string to print after all items have been printed. The
/// default is a newline (`"\n"`).
public func print(_ items: Any..., separator: String = " ", terminator: String = "\n")
第一个参数是任意类型的可变参数,第二个参数是空格符,第三个参数是以换行符结尾
print("111","222","333")//打印结果111 222 333
输入输出参数
- 可以用
inout
定义一个输入输出参数:可以在函数内部修改外部实参的值
var number = 10
func add(_ num:inout Int){
num = 20
}
add(&number)//调用时,在参数前面加上`&`字符
print(number)//20
- 可变参数不能标记为
inout
- inout参数不能有默认值
- inout参数的本质是地址传递(引用传递)
- inout参数只能传入可以被多次赋值的
函数重载(Function Overload)
-
规则
- 函数名相同
- 参数个数不同
||
参数类型不同||
参数标签不同
func sum(v1:Int,v2:Int) -> Int{
v1+v2
}
func sum(v1:Int,v2:Int,v3:Int) -> Int{
v1+v2+v3
}//参数个数不同
func sum(v1:Int,v2:Double) -> Double{
Double(v1)+v2
}//参数类型不同
func sum(v1:Double,v2:Int) -> Double{
v1 + Double(v2)
}//参数类型不同
func sum(a:Int,b:Int) -> Int{
a+b
}//参数标签不同
函数重载注意点:
-
返回值类型与函数重载无关
- 默认参数和函数重载一起使用产生二义性时,编译器并不会报错(在c++中会报错)
func sum(v1:Int,v2:Int) -> Int{
v1+v2
}
func sum(v1:Int,v2:Int,v3:Int = 10) -> Int{
v1+v2+v3
}
//会调用sum(v1:Int,v2:Int)
sum(v1: 10, v2: 20)
- 可变参数、省略参数标签、函数重载一起使用产生二义性时,编译器有可能会报错
func sum(v1:Int,v2:Int) -> Int{
v1+v2
}
func sum(_ v1:Int,_ v2:Int) -> Int{
v1+v2
}
func sum(_ numbers:Int...)->Int{
var total = 0
for number in numbers {
total += number
}
return total
}
//error:Ambiguous use of "sum"
sum(10, 20)
内联函数
- 如果开启了编译器优化(Release模式默认会开启优化),编译器会自动将某些函数变成内联函数
-
将函数调用展开成函数体
-
- 哪些函数不会被内联
- 函数体比较长
- 包含递归调用
- 包含动态派发
- @inline(never)永远不会被内联(即使开启了编译器优化)
@inline(never) func test(){
print("test")
}
- @inline(__always)
开启编译器优化
(即在未开启编译器优化时加always也是不起作用的)后,即使代码很长,也会被内联(递归调用函数、动态派发的函数除外)
- @inline(__always) func test(){
print("test")
}
- 在Release模式下,编译器已经开启优化,会自动决定哪些函数需要内联,因此没必要使用
@inline
函数类型<**>
- 每一个函数都是有类型的,函数类型由形式参数类型、返回值类型组成
func test(){} // () -> Void 或者 ()-> ()
func sum(a:Int, b:Int) -> Int {
a+b
}//(Int,Int) -> Int
//定义变量
var fn:(Int,Int) -> Int = sum
fn(2,3)//5,调用时不需要参数标签
- 函数类型作为函数参数
func sum(v1:Int,v2:Int) -> Int {
v1+v2
}
func difference(v1:Int,v2:Int) -> Int {
v1-v2
}
func printResult(_ mathFn: (Int,Int) -> Int,_ a:Int,_ b:Int) {
print("Result: \(mathFn(a,b))")
}
printResult(sum, 5, 2)
printResult(difference, 5, 2)
- 函数类型作为函数返回值,返回值是函数类型的函数,叫做高阶函数
func next(_ input:Int) -> Int {
input + 1
}
func previous(_ input:Int) -> Int{
input - 1
}
func forward(_ forward:Bool) -> (Int) -> Int {
forward ? next : previous
}
forward(true)(3)//4
forward(false)(4)//2
typealias
-
typealias
用来给类型起别名
typealias Byte = Int8
typealias Short = Int16
typealias Long = Int64
typealias Date = (year:Int,month:Int,day:Int)
func test (_ date:Date){
print(date.0)
print(date.year)
}
test((2019,9,10))
typealias IntFn = (Int,Int) -> Int
func difference(v1:Int,v2:Int) -> Int {
v1 - v2
}
let fn:IntFn = difference
fn(20,10)//10
func setFn(_ fn:IntFn) {}
setFn(difference)
func getFn() -> IntFn {difference}
- 按照Swift标准库的定义,Void就是空元组()
public typealias Void = ()
func sum(_ v1:Int , _ v2:Int){}
func sum(_ v1:Int , _ v2:Int) -> () {}
func sum(_ v1:Int , _ v2:Int) -> Void {}
三种写法等价
嵌套函数
- 将函数定义在函数内部
func forward(_ forward:Bool) -> (Int) -> Int {
func next(_ input:Int) -> Int{
input + 1
}
func previous(_ input:Int) -> Int{
input - 1
}
return forward ? next:previous
}
print(forward(true)(3))//4
print(forward(false)(4))//2
网友评论