【Swift】 - 函数(Functions)总结 - 比较 与 C# 的异同
1.0 函数的定义与调用( Defining and Calling Functions )
习惯了C#了语法,看到下面的这样定义输入参数实在感到非常别扭,func 有点 Javascript的感觉,还算习惯。函数调用与其他语言没什么区别
//有输入参数和返回值的函数 //输入参数为名name,数据类型为String //返回值 String类型 func SayHello(name:String) ->String { return "Hello,"+name; } //调用函数 SayHello("_luo")
2.0 函数参数与返回值 ( Function Parameters and Return Values )
// 2.1 多重输入参数 ( Multiple Input Parameters ) func HalfOpenRangeLength(start:Int,end:Int) ->Int{ return end - start; } // 2.2 无参函数 ( Functions Without Parameters ) func SayHelloWorld()->String{ return "Hello World"; } // 2.3 无返回值函数 ( Functions Without Return Values ) func SayGoodbye(name:String){ println("Goodbye,\(name)"); } // 2.4 多重返回值函数 (Functions with Multiple Return Values ) //你可以用元组(tuple)类型让多个值作为一个复合值从函数中返回。 //计算一个字符串中元音,辅音和其他字母的个数 func Count(str:String)->(vowels:Int,consonants:Int,others:Int){ var vowels=0,consonants=0,others=0; for item in str { switch String(item).lowercaseString{ case "a","e","i","o","u":vowels++; case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":consonants++; default:others++; } } return (vowels,consonants,others); }
3.0 函数参数名称 ( Function Parameter Names )
上面的函数中的参数名仅在函数体中使用,不能这函数调用时使用,这种类型的参数名称为[局部参数名]。
与C#相比,Swift 有外部参数名。
外部参数名,是为了在调用函数时,可以指出各个实参的用途是什么。
(个人觉得实在是太不人性化了,为了知道这个参数的意义还要弄个外部参数名。C#就比较好了 在vs,只要写了注释,调用的时候就会显示各个参数的用途,顿时感觉到vs的强大)
// 3.1 外部参数名 ( External Parameter Names ) //外部参数名写在局部参数名之前,用空格分隔 //如果你提供了外部参数名,那么函数在被调用时,必须使用外部参数名。 //----没有外部参数名的写法👇----- func Join(str1:String,str2:String,joinner:String)->String{ return str1 + joinner + str2; } //当你调用这个函数时,这三个字符串的用途是不清楚的 Join("Hello", "World", ",") //为了让这些字符串的用途更为明显,我们为Join函数添加外部参数名 func Join(string str1:String,toString str2:String,withJoiner joinner:String)->String{ return str1 + joinner + str2; } //现在,你可以使用这些外部参数名以一种清晰地方式来调用函数了: Join(string: "Hello", toString: "World", withJoiner: ","); // 3.2 简写外部参数名 ( Shorthand External Parameter Names ) //如果你需要提供的外部参数名就是局部参数名,那么只写一次参数名并用#号作为前缀就可以了 func ContainsCharacter(#str:String,#char:Character)->Bool{ for item in str{ if(item == char){ return true; } } return false; } ContainsCharacter(str: "klsdkfjoiwenklaskdf", char: "a") // 3.3 默认参数值 ( Default Parameter Values ) // 3.4 默认值参数的外部参数名 ( External Names for Parameters with Default Values ) // 在大多情况下,给带默认值参数起一个外部参数名是很有用的。这样可以保证当函数被调用时,实參的意图是明显的 // 为了使定义外部参数名更加坚定,当你未给带默认值的参数提供外部参数名是,Swift 会自动提供外部名字。此时外部参数名字与局部名字是一样的,就像你已经在局部参数名前写了#一样 func Join(str1:String,str2:String,joinner:String=" ")->String{ return str1 + joinner + str2; } Join("Hello", "World", joinner: "-") // 3.5 可变参数 ( Variadic Parameters ) //通过这变量类型名后加...的方式来定义可变参数 //计算一组任意长度数字的算术平均数 func AritheticMean(numbers:Double...)->Double{ var total:Double=0; for number in numbers{ total += number; } return total / Double(numbers.count); } AritheticMean(1,2,2,1,23,22,12) //注意:一个函数至多能有一个可变参数,而且它必须是参数表中的最后一个 // 3.6 常量参数和变量参数 ( Constant and Variable Parameters ) //函数参数默认上常量。试图这函数体中更改参数值将会导致变异错误,可以通过做参数名前加关键字var来定义变量参数 //使文字右对齐 func TextAlignRight(var str:String,totallength:Int,pad:Character)->String{ let amountToPad = totallength - count(str); if(amountToPad<=0){ return str; } for _ in 1...amountToPad{ str=String(pad) + str; } return str; } TextAlignRight("loding", 10, "-")---------//"----loding" TextAlignRight("Error", 10, "-")----------//"-----Error"
4.0 函数类型(Function Types)
每个函数都有种特定的函数类型,由函数的参数类型和返回类型组成。
例如:
func addTwoInts(a: Int, b: Int) -> Int { return a + b } func multiplyTwoInts(a: Int, b: Int) -> Int { return a * b }
这个例子中定义了两个简单的数学函数:addTwoInts
和 multiplyTwoInts
。这两个函数都传入两个 Int
类型, 返回一个合适的Int
值。
这两个函数的类型是 (Int, Int) -> Int
,可以读作“这个函数类型,它有两个 Int
型的参数并返回一个Int
型的值。”。
下面是另一个例子,一个没有参数,也没有返回值的函数:
func printHelloWorld() { println("hello, world") }
这个函数的类型是:() -> ()
,或者叫“没有参数,并返回 Void
类型的函数”。没有指定返回类型的函数总返回 Void
。在Swift中,Void
与空的元组是一样的。
接下来继续看函数类型的使用,可以发现很类似 C# 的委托了
// 4.1 使用函数类型 (Using Function Types) //在 Swift 中,使用函数类型就像使用其他类型一样。例如,你可以定义一个类型为函数的常量或变量,并将函数赋值给它: var mathFunction: (Int, Int) -> Int = addTwoInts println("Result: \(mathFunction(2, 3))") // prints "Result: 5" //有相同匹配类型的不同函数可以被赋值给同一个变量,就像非函数类型的变量一样: mathFunction = multiplyTwoInts println("Result: \(mathFunction(2, 3))") // prints "Result: 6" //就像其他类型一样,当赋值一个函数给常量或变量时,你可以让 Swift 来推断其函数类型: let anotherMathFunction = addTwoInts // anotherMathFunction is inferred to be of type (Int, Int) -> Int // 4.2 函数类型作为参数类型(Function Types as Parameter Types) //你可以用(Int, Int) -> Int这样的函数类型作为另一个函数的参数类型。这样你可以将函数的一部分实现交由给函数的调用者。 //下面是另一个例子,正如上面的函数一样,同样是输出某种数学运算结果: func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) { println("Result: \(mathFunction(a, b))") } printMathResult(addTwoInts, 3, 5) // prints "Result: 8” // 4.3 函数类型作为返回类型(Function Type as Return Types) //你可以用函数类型作为另一个函数的返回类型。你需要做的是在返回箭头(->)后写一个完整的函数类型。 //下面的这个例子中定义了两个简单函数,分别是 stepForward 和stepBackward。stepForward 函数返回一个比输入值大一的值。stepBackward 函数返回一个比输入值小一的值。这两个函数的类型都是 (Int) -> Int: func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 } //下面这个叫做 chooseStepFunction 的函数,它的返回类型是 (Int) -> Int 的函数。chooseStepFunction 根据布尔值 backwards 来返回 stepForward 函数或 stepBackward 函数: func chooseStepFunction(backwards: Bool) -> (Int) -> Int { return backwards ? stepBackward : stepForward } //你现在可以用 chooseStepFunction 来获得一个函数,不管是那个方向: var currentValue = 3 let moveNearerToZero = chooseStepFunction(currentValue > 0) // moveNearerToZero now refers to the stepBackward() function //上面这个例子中计算出从 currentValue 逐渐接近到0是需要向正数走还是向负数走。currentValue 的初始值是3,这意味着 currentValue > 0 是真的(true),这将使得 chooseStepFunction 返回 stepBackward 函数。一个指向返回的函数的引用保存在了 moveNearerToZero 常量中。 //现在,moveNearerToZero 指向了正确的函数,它可以被用来数到0: println("Counting to zero:") // Counting to zero: while currentValue != 0 { println("\(currentValue)... ") currentValue = moveNearerToZero(currentValue) } println("zero!") // 3... // 2... // 1... // zero!
5.0 嵌套函数(Nested Functions)
在上面的例子中,你所见到的所有函数都叫全局函数(global functions),它们定义在全局域中。你也可以把函数定义在别的函数体中,称作嵌套函数(nested functions)。
默认情况下,嵌套函数是对外界不可见的,但是可以被他们封闭函数(enclosing function)来调用。一个封闭函数也可以返回它的某一个嵌套函数,使得这个函数可以在其他域中被使用。
你可以用返回嵌套函数的方式重写 chooseStepFunction
函数:
func chooseStepFunction(backwards: Bool) -> (Int) -> Int { func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 } return backwards ? stepBackward : stepForward } var currentValue = -4 let moveNearerToZero = chooseStepFunction(currentValue > 0) // moveNearerToZero now refers to the nested stepForward() function while currentValue != 0 { println("\(currentValue)... ") currentValue = moveNearerToZero(currentValue) } println("zero!")
结果:
// -4...
// -3...
// -2...
// -1...
// zero!