函数
多参数
我们设计一个能求矩形面积的函数,输入长和宽,就得出面积:
func rectangle(length: Double, width: Double) -> Double {
return length * width
}
print(rectangle(length: 15, width: 20.8) ) // 312.0
这里,我们设计了length
和width
两个参数,分别代表了长方形的长
和宽
,并且为他们指定了Double
的数据类型。输出的结果也指定为Double
类型。包裹代码中,让length
和width
相乘,得到的就是矩形的面积
,用return
这个关键字,将结果返出函数。
在函数外面,任意给这两个参数指定某个长度值,就得到了相应的面积。
参数还可以更灵活。
我们继续扩展这个函数。现在,我想让函数能计算面积的同时还能计算周长,可以这样设计:
func rectangle(length: Double, width: Double, isPerimeter:Bool ) -> Double {
if isPerimeter {
return (length + width) * 2
} else {
return length * width
}
}
let area = rectangle(length: 10, width: 26, isPerimeter: false)
let perimeter = rectangle(length: 10, width: 26, isPerimeter: true)
print("长方形的面积是\(area),周长是\(perimeter)")
注意看,参数还能使用布尔值,包裹代码中就可以做一个判断,如果isPerimeter
是true
,我们就计算周长,否则,还是计算面积。这样,我在下面引用函数的时候,如果想计算面积,我就将isPerimeter
设置为false
,想计算周长,就将这个参数设置为true
。
怎么样,短短的几行代码,仅仅是参数不同,就可以实现不同的功能。在实际应用时,将大幅节省你的代码量,出错时,也容易排查到是哪里出了问题。
默认参数
上面这个例子中,我们想求矩形的面积,仍然要指定isPerimeter: false
,这样显得有点啰嗦,能不能直接默认就是求面积呢?
我们可以使用默认参数:
func rectangle(length: Double, width: Double, isPerimeter: Bool = false ) -> Double {
if isPerimeter {
return (length + width) * 2
} else {
return length * width
}
}
let area = rectangle(length: 10, width: 26)
let perimeter = rectangle(length: 10, width: 26, isPerimeter: true)
在参数中,我们指定isPerimeter
的默认值是false
,这样,后面我们调用函数时,可以不用指定这个参数的值了,函数会调用默认值。
而当我们想修改默认值时,只需要再次指定,这样,默认值会被覆盖,使用我们调用函数时指定的新值。
返回可选型
上面这个例子中,我们还可以这样改造。当指定isPerimeter为true时,计算周长,而当isPerimeter为false时,什么都不做,返回空值。
func rectangle(length: Double, width: Double, isPerimeter: Bool ) -> Double? {
if isPerimeter {
return (length + width) * 2
} else {
return nil
}
}
let area = rectangle(length: 10, width: 26, isPerimeter: false)
注意看,我们返回值加了个?
,如果不加,系统会报错。因为我们返回的值可能是Double
型,也可能是nil
型,这样的不确定性,不就是我们之前说过的可选型
吗?所以,我们指定函数的返回值是一个Double可选型
,这样,系统就不会报错了。
多返回值
如果,我想一次性得到周长和面积,又该怎么办呢?好办!
func rectangle(length: Double, width: Double ) -> (area: Double, perimeter: Double) {
let area = length * width
let perimeter = (length + width) * 2
return (area, perimeter)
}
let newRectangle = rectangle(length: 15, width: 20.2)
print("长方形的面积是\(newRectangle.area),周长是\(newRectangle.perimeter)")
想要从函数中返回多个值,需要借助元组。
首先,在返回类型中,我们要分别指定返回的值及其类型。使用return
时,将值用元组的形式放在返回值中。最后,调用的时候,用类似调用属性的方式.area
,.perimeter
调用相应的值。
参数的标签
参数已经有名称了,比如上面的length
和width
。Swift仍然具有给参数名再加标签的功能,我们用开始最简单的函数举例。
func rectangle(chang length: Double, kuan width: Double) -> Double {
return length * width
}
print(rectangle(chang: 15, kuan: 20.8) ) // 312.0
看到没有,我们在length
前面加了个chang
,width
前面加了个kuan
,这样,我们在调用的时候,直接使用chang
,kuan
就行了。
我们还可以忽略标签:
func rectangle(_ length: Double, _ width: Double) -> Double {
return length * width
}
print(rectangle(15,20.8) ) // 312.0
使用_
,意思是可以忽略标签,因为参数名本身就是默认标签。这样,我们在调用函数的时候,就不用指定标签,直接按顺序赋值即可。
可变参数
在前几个案例中,我们定义好参数,在调用函数的时候,要对参数一一对应的赋值。
然而,有些情况,我们并不能提前确定好参数的具体数量。
比如,我想实一个计算商品总价的程序,把我买的商品价格都输入进去,然后算总价。实际上也就是任意n个数的求和。我们可以做样做:
func totalValue(_ items: Double...) -> Double {
var sumPrice: Double = 0
for i in items {
sumPrice += i
}
return sumPrice
}
let totalYesterday = totalValue(20.5,58.3,88.2)
let totalToday = totalValue(322.5,909.2,69.9,12.6)
分析这段代码,首先在参数数据类型的后面加...
,然后在包裹的代码块中,遍历参数,然后累加。
最后,在调用函数的时候,我们实际上可以输入满足数据类型的任意数量的参数。
输入输出参数
到目前位置,我们给出的参数,在函数中,都是老老实实的直接使用。如果我在函数中改变参数行不行呢?答案是不行,比如参数给了a = 3
,我们不能在函数中这样改变a +=1
,这样系统是会报错的,因为默认情况下,参数是常量。
但是,Swift仍然给了我们一个渠道,可以修改参数的值,这就是输入输出参数。看下面这个例子,我们输入一个人的身高,但是考虑到有鞋的高度,因此我做了一个函数,能够将身高减去一个高度,再返回出来。
func person(stature: inout Double) -> Double{
stature = stature - 0.03
return stature
}
var Tom = 1.78
person(stature: &Tom)
print(Tom)
首先,我们在参数中加了一个关键字inout
,表示这个参数是一个输入输出参数。(注意,可变参数不能加inout
,你可以试一下。)
接着,我们在代码块中对参数值进行了-0.03
的操作。
在调用的时候,我先定义了一个变量:Tom
的测量身高是1.78
。然后调用了一下函数,这个函数对stature参数进行了修改处理。
在引用的时候,我们使用了&
符号,这个类似与C语言中的指针,就是我们改的变量Tom
所指向的内存地址。产生实际上的效果是,函数对外部的变量值进行了修改,因此,我们再次调用Tom
的时候,就是修改过的值。
如果你尝试像这样直接调用函数,print(person(stature: 1.78))
,系统会提示,说字面量不可修改
,因为你已经用1.78
把参数stature
写死了,需要把1.78
这个位置换成可修改的变量
,才能完成参数的加工修改。
小结与预告
好了,本节内容先告一段落。
我们介绍了函数的参数和返回值的一些衍生概念。
下节,我们将拓展数据类型的概念。
网友评论