Swift学习:函数

本篇将详细总结介绍Swift函数的用法;
函数是一段完成特定任务的独立代码片段。你可以通过给函数命名来标识某个函数的功能,这个名字可以被用来在需要的时候"调用"这个函数来完成它的任务。

主要内容:

1.函数的定义与调用
2.函数参数与返回值
3.函数外部参数名和参数名称
4.默认参数
5.可变参数
6.输入输出参数
7.函数类型
8.函数类型

一、函数的定义与调用

下面演示了在Swift中,定义函数和调用函数的基本操作:

//定义函数
func greet(person: String) -> String {
    let greeting = "Hello, " + person + "!"
    return greeting
}

//调用函数
print(greet(person: "Anna"))         // 打印 "Hello, Anna!”

func greetAgain(person: String) -> String {
    return "Hello again, " + person + "!"
}
print(greetAgain(person: "Anna"))    // 打印 "Hello again, Anna!”

二、函数参数与返回值

2.1.无参,有返回值函数

func sayHi() -> String {
    return "Hi!"
}
print(sayHi())

2.2.多参,有返回值函数

func sayHi(person: String, greet: String) -> String {
    let greetString = greet  + person
    return greetString
}
print(sayHi(person: "zhoushuai", greet: "Hi!"))

2.3.无返回值函数

严格意义上,虽然没有返回值,但是sayHello函数依然返回了值。没有定义返回类型的函数会返回一个特殊的Void值。它其实是一个空的元组(tuple),没有任何元素,可以写成()

func sayHi(person: String) {
    print("Hi-Hi, \(person)!")
}
sayHi(person: "Tom”)  //打印 "Hi-Hi, Tom!”

//sayHello函数与下面的两个函数,会被Swift识别为同一种函数,进而报错重复定义。
/*
func sayHi(person: String) ->(){
    print("Hello, \(person)!")
}

func sayHi(person: String) ->Void {
    print("Hello, \(person)!")
}
*/

2.4.多重返回值函数

可以用元组(tuple)类型让多个值作为一个复合值从函数中返回,即返回多个参数

func findMaxMin(array:[Int]) ->(max:Int,min:Int){
    let max = array.max()
    let min = array.min()
    return (max!,min!)
}
let bounds = findMaxMin(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
//打印 "min is -6 and max is 109

2.5.可选返回值类型

func findMaxMin2(array:[Int]) ->(max:Int,min:Int)?{
    guard !array.isEmpty else{
        return nil
    }
    
    var maxVlaue = array[0]
    var minValue = array[0]
    for number in array{
        maxVlaue = maxVlaue > number ? maxVlaue : number
        minValue = minValue < number ? minValue : number
    }
    //返回的类型是可选型,因为结果有可能是nil
    return (maxVlaue, minValue)
}
if let bounds2 = findMaxMin2(array: [1, 2, 3, 4, 5, 6]){
    print("min is \(bounds2.min) and max is \(bounds2.max)")
}

注意:可选元组类型如 (Int, Int)? 与元组包含可选类型如 (Int?, Int?) 是不同的.可选的元组类型,整个元组是可选的,而不只是元组中的每个元素值。

2.6.无参,无返回值函数

func sayHiHi(){
    print("sayHiHi:无参五返回值的函数!")
}
sayHiHi()

三、函数外部参数名和参数名称

每个函数参数都有一个外部参数名(参数标签)以及参数名称,只不过默认情况下,函数参数直接使用参数名来作为它们的外部参数名。下面来总结函数外部参数名的各种用法。

3.1.指定外部参数名,让函数表意更明确

函数外部参数名的使用能够让一个函数在调用时更有表达力,更类似自然语言,并且仍保持了函数内部的可读性以及清晰的意图。

//正常写法:
func sayHelloTo(name: String , greeting: String) -> String{
    return "\(greeting), \(name)!"
}

print(sayHelloTo(name: "风恣", greeting: "Hello”)) 
//打印:"Hello,风恣!"

//改进上面的函数,为第二个参数指定外部参数名,让表意更加明确
func sayHelloTo(name: String, withGreetingWord greeting:String) -> String{
    return "\(greeting),\(name)"
}
print(sayHelloTo(name: "FengZi", withGreetingWord: "Hello"))
//打印:"Hello,FengZi"

特别说明
一般情况下,第一个参数不设置外部参数名,因为第一个参数的外部参数名是隐藏在函数名中的。

3.2.忽略参数标签

有时候,使用外部参数名反而会使函数更加繁琐,这又需要隐藏外部参数名:这时候使用下划线"_"来代替一个明确的参数标签。

//正常写法:
func mutipleOf(num1: Int, and num2:Int)-> Int{
    return num1 * num2
}
mutipleOf(num1: 1, and: 6)    //6

//改进1:忽略参数标签
func  mutipleOf(num1:Int , num2:Int) -> Int{
    return num1 * num2;
}
mutipleOf(num1: 1, num2: 6)   //6

//改进2:彻底不使用参数名,使用下划线省略
func mutiply(_ num1:Int, _ num2:Int) -> Int{
    return num1 * num2
}
mutiply(1, 6)                //6

四、默认参数

定义函数的时候,可以给某些参数设置默认值(Deafult Value),当默认值被定义后,调用这个函数时可以忽略这个参数。
下面的函数包括两个默认参数,而且设置的默认参数都要在非默认参数后面。

func playMusic(name: String, instrument:String = "drum", sound:String = "咚咚咚。。。") -> String{
    let scene = name + " play the " + instrument + "," + sound;
    print(scene)
    return scene;
}

//使用了默认参数的参数, 相关的默认参数可以不用传值
playMusic(name: "zhoushuai”)

//对于默认参数,可以有选择的传入值
playMusic(name: "zhoushuai", instrument: "panio")
playMusic(name: "zhoushuai", instrument: "panio" ,sound: "lingling~")

//测试打印:
//zhoushuai play the drum,咚咚咚。。。
//zhoushuai play the panio,咚咚咚。。。
//zhoushuai play the panio,lingling~

五、可变参数

一个可变参数可以接受零个或多个值。函数调用时,你可以用可变参数来指定函数参数传入不确定数量的输入值。通过在变量类型名后面加入(...)的方式来定义可变参数。下面的算术平均函数演示了可变参数的用法:

func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)   //返回3.0, 是这5个数的平均数。

arithmeticMean(3, 8.25, 18.75)  //返回10.0, 是这3个数的平均数。

注意:一个函数只能拥有一个可变参数

六、输入输出参数

函数参数默认是常量形参,所以我们在函数中对其修改都不会对参数的原值产生影响。为了解决这个问题,我们可以将这些需要修改的参数定义为输入输出参数。

var somInt = 10;
//普通函数:报错,因为num是常量,不能被再次修改
/*
func modifyNum(num:Int){
    num = num * 2;
}
*/

//带有输入输出函数的函数
func modifyNum2(num:inout Int){
    num = num * 2
}
modifyNum2(num: &somInt)
print(somInt)           //20,someIn被修改

注意:
1.只能传递变量给输入输出参数,而不能是常量或者字面量,因为这些量是不能被修改的;
2.传入参数作为输入输出参数时,需要在参数名前添加&符号,表示这个值可以被修改;

七、函数类型

如同参数有整型,布尔型等参数类型一样,每个函数都有种特定的函数类型。函数的类型由函数的参数类型和返回值类型组成。下面举例说明:

1.以下两个函数具有相同的函数类型:(Int,Int)->Int

func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}

func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
    return a * b
}

2.没有参数也没有返回值的函数类型:()->Void

func printHelloWorld() {
    print("hello, world")
}

3.使用函数类型

3.1定义一个函数类型的变量或常量,然后可以使用适当函数为其赋值

下面的mathFunction变量,经过赋值之后,指向了addTwoInts函数,所以它也可以当做addTwoInts函数使用

var mathFunction:(Int,Int)->Int = addTwoInts

//赋值了加法函数:addTwoInts
print(mathFunction(3,4))         //7

//赋值了乘法函数:multiplyTwoInts
mathFunction = multiplyTwoInts;
print(mathFunction(3,4))         //12
3.2函数类型做为参数类型

函数类型也可以作为另一个函数的参数类型,这样我们就可以将函数的一部分实现留给函数的调用者来提供。

//测试1:
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)          //打印 "Result: 8”
printMathResult(multiplyTwoInts, 3, 5)   //打印:"Result: 15"

//测试2:
//生成随机数组成的数组
var array: [Int] = []
for _ in 0..<6{
    let max=20
    let randNum0=arc4random()%UInt32(max)
    let randNum1=Int(randNum0)
    if(array.contains(randNum1)){
        continue;
    }
    array.append(randNum1)
}

print(array)       //[12, 9, 19, 13, 3]

//自定义排序方法1:从大到小排序
func biggerNumFirst(num1:Int, num2:Int) -> Bool{
    return num1 > num2
}
//自定义排序方法2:将数字转化为字符串, 按照字符换的字典排序
func compareByNumberString(num1: Int, num2: Int) ->Bool{
    return String(num1) > String(num2)
}
//自定义排序方法3:距离某个数字最近
func nearTo10(num1: Int, num2: Int) ->Bool{
    return abs(num1 - 10) < abs(num2 - 10) ? true :false
}

array.sort(by: biggerNumFirst(num1:num2:))
array.sort(by: compareByNumberString)
array.sort(by: nearTo10)
//测试打印:
//[19, 13, 12, 9, 3]
//[9, 3, 19, 13, 12]
//[9, 12, 13, 3, 19]
3.3.函数类型作为返回值类型

你可以用函数类型作为另一个函数的返回类型。你需要做的是在返回箭头(->)后写一个完整的函数类型。

func getMathFunction(symbol: String)->(Int,Int)->Int{
    if symbol == "*" {
        return multiplyTwoInts;
    }else{
        return addTwoInts
    }
}

//传入不同的字符串参数,会返回不同的函数
var function = getMathFunction(symbol: "*")
function(1,2)    //2
function = getMathFunction(symbol: "abcdefg")
function(1,2)    //3

八、嵌套函数

通常,我们见到的都是全局函数,即定义在全局域中的函数。我们也可以把函数定义在别的函数体中,称作嵌套函数。

func getMathFunction2(symbol: String)->(Int,Int)->Int{
    func mathFunc1(a:Int,b:Int)->Int{
        return a - b
    }
    
    func mathFunc2(a: Int, b: Int) -> Int{
        return a * b
    }
    
    if symbol == "*" {
        return mathFunc2;
    }else{
        return mathFunc1;
    }
}


var method = getMathFunction2(symbol: "*")
method(5,6)     //30
method = getMathFunction2(symbol: "123123")
method(5,6)     //-1
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容

  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,732评论 2 9
  • 不带参数的函数 func helloWord() -> String { return "Hello word" ...
    cochn阅读 163评论 0 3
  • 定义与调用 用func作为前缀来标志这是一个函数,用 (->) 加返回类型的名字表示该函数返回什么类型 参数与返回...
    JaneJie阅读 345评论 0 1
  • 作为女孩子,每个人都想有个依靠、有依赖的对象。生活中总有一些不如意,需要依靠的我们,变成了自己不想成为的样子—...
    稻麦香阅读 322评论 0 0
  • 想必对开始吃素食,或者准备吃素的人来说,有一个问题无法避免,那就是能不能吃蛋。实际上,蛋奶一直是素食争议之物。我也...
    金黄鱼阅读 258评论 0 0