[swift-day04-函数]
- 以 func 作为前缀。指定函数返回类型时,用返回箭头 ->(一个连字符后跟一个右尖括号)后跟返回类型的名称的方式来表示。函数的定义的 func+参数名+(参数名:参数类型)->返回类型
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//以 func 作为前缀。指定函数返回类型时,用返回箭头 ->(一个连字符后跟一个右尖括号)后跟返回类型的名称的方式来表示。函数的定义的 func+参数名+(参数名:参数类型)->返回类型
func printHello(personName:String) ->String{
let greeting = "Hello" + "Wrold!"
return greeting;
}
//无参函数
func sayHelloWorld() -> String{
return "Hello Wrold!";
}
//尽管这个函数没有参数,但是定义中在函数名后还是需要一对圆括号。当被调用时,也需要在函数名后写一对圆括号
print(sayHelloWorld())
//多参数函数:函数可以有多种输入参数,这些参数被包含在函数的括号之中,以逗号分隔
func sayHeoll(personName1:String,personName2:String)->String{
return personName1 + personName2;
}
print(sayHeoll("Hello", personName2: "Wrold"))
//无返回值函数,严格上来说,虽然没有返回值被定义,printHello1() 函数依然返回了值。没有定义返回类型的函数会返回特殊的值,叫 Void。它其实是一个空的元组(tuple),没有任何元素,可以写成()
func printHello1(){
print("Hello Wrold");
}
printHello1();
//多重返回值函数
//你可以用元组(tuple)类型让多个值作为一个复合值从函数中返回
func minMax(Array:[Int]) -> (min:Int,max:Int){
var currentMin = Array[0];
var currentMax = Array[0];
for value in Array[1..<Array.count]{
if value < currentMin{
currentMin = value;
}else if value > currentMax{
currentMax = value;
}
}
return (currentMin,currentMax);
}
let bounds = minMax([-10,2,-8,8,3,10,3,27,-11]);
print("min is \(bounds.min) and max is \(bounds.max)")
//可选元祖返回类型
//如果函数返回的元组类型有可能整个元组都“没有值”,你可以使用可选的(Optional) 元组返回类型反映整个元组可以是nil的事实。你可以通过在元组类型的右括号后放置一个问号来定义一个可选元组,例如(Int, Int)?或(String, Int, Bool)?
//可选元组类型如(Int, Int)?与元组包含可选类型如(Int?, Int?)是不同的.可选的元组类型,整个元组是可选的,而不只是元组中的每个元素值。
func minMax2(Array:[Int]) -> (min:Int,max:Int)?{
var currentMin = Array[0];
var currentMax = Array[0];
for value in Array[1..<Array.count]{
if value < currentMin{
currentMin = value;
}else if value > currentMax{
currentMax = value;
}
}
return (currentMin,currentMax);
}
//使用可选绑定来检查minMax(_:)函数返回的是一个实际的元组值还是nil
if let bounds = minMax2([8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
}
//函数参数名称,函数参数都有一个外部参数名(external parameter name)和一个局部参数名(local parameter name)。外部参数名用于在函数调用时标注传递给函数的参数,局部参数名在函数的实现内部使用
func sayHeoll3(personName1:String,personName2:String)->String{
return personName1 + personName2;
}
//一般情况下,第一个参数省略其外部参数名,第二个以及随后的参数使用其局部参数名作为外部参数名。所有参数必须有独一无二的局部参数名。尽管多个参数可以有相同的外部参数名,但不同的外部参数名能让你的代码更有可读性
sayHeoll3("hello", personName2: "wrold")
//指定外部参数名你可以在局部参数名前指定外部参数名,中间以空格分隔
func sayHeoll4(Name1 personName1:String,Name2 personName2:String){
print(personName1 + personName2);
}
sayHeoll4(Name1: "hello", Name2: "hello")
//忽略外部参数名,如果你不想为第二个及后续的参数设置外部参数名,用一个下划线(_)代替一个明确的参数名
func sayHeoll5(personName1:String,_ personName2:String){
print(personName1 + personName2);
}
sayHeoll5("hello", "wrold")
//默认参数值(Default Parameter Values),可以在函数体中为每个参数定义默认值(Deafult Values)。当默认值被定义后,调用这个函数时可以忽略这个参数
func sayHeoll6(personName1: String = "hello",personName2:String = "wrold"){
print(personName1 + personName2);
}
sayHeoll6("h",personName2: "w");//输出hw
sayHeoll6();//输出hellowrold
//可变参数,一个可变参数可以接受零个或多个值。函数调用时,你可以用可变参数来指定函数参数可以被传入不确定数量的输入值。通过在变量类型名后面加入(...)的方式来定义可变参数,可变参数的传入值在函数体中变为此类型的一个数组。例如,一个叫做 strings 的 String... 型可变参数,在函数体内可以当做一个叫 strings 的 [String] 型的数组常量
func sayHello7(strings:String...,personName2:String = "1"){
var totalString = String()
for string in strings{
totalString += string;
}
totalString += personName2;
print(totalString)
}
//注意:一个函数最多只能有一个可变参数
sayHello7("1","2","3","4","5",personName2:"yy")//输出12345yy
//常量参数和变量参数,函数参数默认是常量。试图在函数体中更改参数值将会导致编译错误。这意味着你不能错误地更改参数值。但是,有时候,如果函数中有传入参数的变量值副本将是很有用的。你可以通过指定一个或多个参数为变量参数,从而避免自己在函数中定义新的变量。变量参数不是常量,你可以在函数中把它当做新的可修改副本来使用。通过在参数名前加关键字 var 来定义变量参数
//注意:对变量参数所进行的修改在函数调用结束后便消失了,并且对于函数体外是不可见的。变量参数仅仅存在于函数调用的生命周期中
func alignRitht(var string:String,totalLength:Int,str:Character) -> String{
let amount = totalLength - string.characters.count;
if amount < 1 {
return string;
}
let padString = String(str)
for _ in 1...amount{
string = padString + string;
}
return string;
}
let originalString = "hello";
let paddedString = alignRitht(originalString, totalLength: 12, str: "*")
print(paddedString)//输出结果: *******hello
//变量参数,正如上面所述,仅仅能在函数体内被更改。如果你想要一个函数可以修改参数的值,并且想要在这些修改在函数调用结束后仍然存在,那么就应该把这个参数定义为输入输出参数(In-Out Parameters)。
// 定义一个输入输出参数时,在参数定义前加 inout 关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。想获取更多的关于输入输出参数的细节和相关的编译器优化,请查看输入输出参数一节。
//你只能传递变量给输入输出参数。你不能传入常量或者字面量(literal value),因为这些量是不能被修改的。当传入的参数作为输入输出参数时,需要在参数名前加&符,表示这个值可以被函数修改。
//输入输出参数不能有默认值,而且可变参数不能用 inout 标记。如果你用 inout 标记一个参数,这个参数不能被 var 或者 let 标记
func swap(inout a:Int,inout _ b:Int){
let temporaryA = a;
a = b;
b = temporaryA;
}
var someInt = 100;
var anotherInt = 110;
swap(&someInt, &anotherInt)
print("someInt is now\(someInt),and anotherInt is now\(anotherInt)")//someInt is now110,and anotherInt is now100
//每个函数都有种特定的函数类型,由函数的参数类型和返回类型组成。
//上面的例子swap函数类型是(inout,inout)->void
//使用函数类型在 ,Swift 中,使用函数类型就像使用其他类型一样。例如,你可以定义一个类型为函数的常量或变量,并将适当的函数赋值给它:
func multiplyTwoInts(a: Int, _ b: Int) -> Int {
return a * b
}
//“定义一个叫做 multiplyTwoInts 的变量,类型是‘一个有两个 Int 型的参数并返回一个 Int 型的值的函数’,并让这个新变量指向 mathFunction 函数”。multiplyTwoInts 和 mathFunction 有同样的类型,所以这个赋值过程在 Swift 类型检查中是允许的。现在,你可以用 mathFunction 来调用被赋值的函数了
var mathFunction: (Int, Int) -> Int = multiplyTwoInts;
print(mathFunction(2, 3))//6
//有相同匹配类型的不同函数可以被赋值给同一个变量,就像非函数类型的变量一样
func multiplyTwoInts1(a: Int, _ b: Int) -> Int {
return a + b
}
mathFunction = multiplyTwoInts1;
print(mathFunction(2,3));//5
//函数类型作为参数类型,你可以用(Int, Int) -> Int这样的函数类型作为另一个函数的参数类型。这样你可以将函数的一部分实现留给函数的调用者来提供。
func printMathResult(mathFunction1: (Int, Int) -> Int,_ a: Int,_ b:Int){
print("Result: \(mathFunction1(a ,b))")
}
//函数类型作为返回类型,你可以用函数类型作为另一个函数的返回类型。你需要做的是在返回箭头(->)后写一个完整的函数类型
func chooseStepFunction(backwards: Bool) -> (Int,Int) -> Int {
return backwards ? multiplyTwoInts : multiplyTwoInts1
}
let currentValue = 3
let moveNearerToZero = chooseStepFunction(currentValue > 0)
print(moveNearerToZero(2,5))//10
//嵌套函数把函数定义在别的函数体中,称作嵌套函数(nested functions),默认情况下,嵌套函数是对外界不可见的,但是可以被它们的外围函数(enclosing function)调用。一个外围函数也可以返回它的某一个嵌套函数,使得这个函数可以在其他域中被使用。
func chooseStepFunction2(backwards: Bool) -> (Int,Int) -> Int{
func multiplyTwoInts(a: Int, _ b: Int) -> Int {
return a * b
}
func multiplyTwoInts1(a: Int, _ b: Int) -> Int {
return a + b
}
return backwards ? multiplyTwoInts : multiplyTwoInts1
}
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}