Swift编程权威指南(第2版)第 12 章 函数笔记

//1.无参函数

funcprintGreeting() {

print("Hello, playground.")

}

printGreeting()

//2.有参函数(一个参数)

funcprintPersonalGreeting(name:String){

//(name: String)形参+实参的类型

print("Hello\(name), welcome to your playground.")

}

printPersonalGreeting(name:"yang")

//3.有参函数(多个参数)

funcdivisionDescriptionFor(numerator:Double, denominator:Double) {

print("\(numerator) divided by\(denominator) equals\(numerator / denominator)")

}

divisionDescriptionFor(numerator:9.0, denominator:3.0)

//4.参数的名字

有时候让函数体外可见的参数不同于内部也是有用的,也就是调用函数的时候用一个参数名字,在函数体内用另一个名字(这时调用函数的参数叫做外部参数)

funcprintPersonalGreeting(to name:String) {

print("Hello\(name), welcome to your playground.")

}

printPersonalGreeting(to:"Matt")

//现在printPersonalGreeting(to:)有了一个外部参数to:这个参数能让函数读起来更像日常说话

//函数内还得用name(在函数内部name的含义很清楚)

//内外结合

//func divisionDescriptionFor(numerator: Double, denominator: Double) {

//    print("\(numerator) divided by \(denominator) equals \(numerator / denominator)")

//}

//divisionDescriptionFor(numerator: 9.0, denominator: 3.0)

//你可能注意到了divisionDescription的末尾是介词而printPersonalGreeting的介词在括号内

//Swift的命名指南建议如果一个函数有多个参数形成单一的概念那么介词应该放在函数名的结尾,如果没有多个参数形成单一的概念介词在括号内(那如果多个参数,分别代表不同的概念,介词也放在括号内?放一个?)

//5.变长参数

变长参数接受零个或更多输入值作为实参函数只能有一个变长参数而且应该是参数列表的最后一个参数值在函数内部以数组的形式呈现

funcprintPersonalGreetings(to names:String...) {

fornameinnames {

print("Hello\(name), welcome to the playground.")

}

}

printPersonalGreetings(to:"Alex","Chris","Drew","Pat")

6.默认参数值

//Swift的参数可以接受默认值,放在参数列表的末尾,如果形参有默认值,那么在调用参数时可以省略实参

funcdivisionDescriptionFor(numerator:Double,denominator:Double,withPunctution punctuation:String="."){

print("\(numerator) divided by\(denominator) equals\(numerator / denominator)\(punctuation)")

}

//如果前面已经有一个没有默认值的divisionDescriptionFor方法,就会先调用前面的方法,调用完就结束了,不会往下执行

divisionDescriptionFor(numerator:9.0, denominator:9.0)

divisionDescriptionFor(numerator:9.0, denominator:3.0, withPunctution:"!”)

1.In-out 参数

出于某种原因 函数有时候需要修改实参的值

In-out 参数能让函数 影响函数体以外的变量

注意:

In-out 参数不能有默认值

变长参数不能标记为In-out

一个函数接受一个错误信息为实参

并根据某些条件在后面添加信息

varerror="The request failed:"

func appendErrorCode(_ code:Int(错误码,类型为Int,注意我们给这个参数的外部名是_ 有特殊含义 在参数名前用_ 函数被调用的时候省去外部名,与函数名重复 ),toErrorString errorString:inout(inout加在String前面表示这个函数期望一个特殊的String 一个inout类型的string 调用这个函数时,传递给inout参数的变量要在前面加上&??? 这表示函数可以修改这个变量 在这里errorString被改为The request failed: bad request)String(第二个是命名为toErrorString 的 inout参数在名字前用inout关键字标记?)类型是stringtoErrorString 是外部名 用来调用函数 而errorString是内部名 在函数内部使用)){

ifcode==400{

errorString+=" bad request."

}

}

appendErrorCode(400,toErrorString:error)

error

//从函数返回值

//函数结束后可以返回一些信息,这些信息称为函数的返回值。常见的情况是写下一个函数来完成一些工作,然后返回一些数据

funcdivisionDescriptionFor(numerator:Double,

denominator:Double,

withPunctuation punctuation:String=".") ->String{

return"\(numerator) divided by\(denominator) equals\(numerator / denominator)\(punctuation)"

}

print(divisionDescriptionFor(numerator:9.0, denominator:3.0, withPunctuation:"!"))

//可以给其他函数使用

// 2.多个返回值

//函数可以返回不止一个值

//Swift用元组数据类型来做到这一点

//元祖是相关值的有序列表

funcsortedEvenOddNumbers(_numbers: [Int](接受整数数组作为唯一的参数)) -> (evens: [Int], odds: [Int]) {

varevens = [Int]()

varodds = [Int]()

fornumberinnumbers {

ifnumber %2==0{

evens.append(number)

}else{

odds.append(number)

}

}

return(evens, odds)

}

//

//嵌套函数

//Swift的函数定义可以嵌套嵌套函数在另一个函数定义的内部声明并实现嵌套函数在包围它的函数以外不可用当你需要一个函数只在另一个函数内部做一些事情时可以这样用调某一个函数嵌到他里面的函数在执行

funcareaOfTriangleWith(base:Double, height:Double) ->Double{

letnumerator = base * height

funcdivide() ->Double{

//divide()没有参数,返回Double

returnnumerator /2

}

//调用divide(),返回结果给外部

returndivide()

}

areaOfTriangleWith(base:3.0, height:5.0)

//divide()函数还用到了areaOfTriangleWith(base:height:)中定义的常量numerator这个常量是在divide()的闭合作用域中定义的(不是在areaOfTriangleWith定义?)函数中『』都称为函数的作用域在本例中常量numerator和divide()都被areaOfTriangle(withBase:andHeight:)的作用域包围。

//函数的作用域描述了实例或函数的可见性numerator对函数divide()可见是因为两者共享同一个闭合作用域

//同一个作用域互相可用

元祖是开发者认为具有逻辑关联的两个 或 多个值的有限组合  不同的值被组合成单个复合值

组合的结果  是一个元素的有序列表

创建一个元祖来组合statusCode和errorString

varstatusCode:Int=418

varerrorString:String="The request failed with the error:"

switchstatusCode{

case100,101:

errorString+=" Informational, \(statusCode)."

case204:

errorString+=" Successful but no content, 204."

case300...307:

errorString+=" Redirection, \(statusCode)."

case400...417:

errorString+=" Client error, \(statusCode)."

case500...505:

errorString+=" Server error, \(statusCode)."

caseletunknownCodewhere(unknownCode>=200&&unknownCode<300)

||unknownCode>505:

errorString="\(unknownCode) is not a known error code."

default:

errorString="Unexpected error encountered."

}

leterror=(statusCode,errorString) 放进一对圆括号里  就可以创建元祖  结果被付给error常量

只要逻辑相关,类型不同也可以组成元祖

因为是有序的 所以可以用位置访问

Swift的元祖也可以保存命名元素

元祖的命名元素能使代码更可读

要理解error.0和error.1代表什么值有些困难

利用命名元素直接指向其含义可能更容易

leterror=(code:statusCode,error:errorString)

error.code

error.error

不取名的话只能访问其位置

现在可以通过名字来访问

元祖

leterror=(code:statusCode,error:errorString)

error.code

error.error

letfirstErrorCode=404 (表示两个不同Web请求的HTTP状态码)

letsecondErrorCode=200

leterrorCodes(组合状态码的元祖)=(firstErrorCode,secondErrorCode)

switcherrorCodes{

//switch 语句会匹配几个分支来判断这些请求可能产生什么样的404组合

case(404,404):

print("No items found.")

case(404,_):(_匹配任何值的通配符)

print("First item not found.")

case(_,404):

print("Second item not found.")

default:

print("All items found.")

}

这段代码先添加了几个新常量

函数

1.

多个返回值

函数可以返回不止一个值  Swift用元祖数据类型来做到这一点

接受整数数组作为唯一的参数 (指evens:[Int],odds:[Int]后面的[]吗?)【(_ numbers:[Int])】并返回一个命名元祖 元祖的组成部分是有名字的evens:[Int],odds:[Int]就有名字

funcsortedEvenOddNumbers(_ numbers:[Int])->(evens:[Int],odds:[Int]){

varevens=[Int]()(在函数的内部初始化数组)

varodds=[Int]()(在函数的内部初始化数组

fornumberinnumbers{

//遍历函数参数numbers里的整数数组(不是元祖吗)

ifnumber%2==0{

evens.append(number) 偶数添加到evens

}else{

odds.append(number) 基数添加到odds

}

}

return(evens,odds)

}

letaBunchOfNumbers=[10,1,4,3,57,43,84,27,156,111]

lettheSortedNumbers=sortedEvenOddNumbers(aBunchOfNumbers)

print("The even numbers are: \(theSortedNumbers.evens);

the odd numbers are: \(theSortedNumbers.odds)")

首先创建一个数组存放一组整数

接着把数组传递给sortedEvenOddNumbers(_:)函数

并将返回值赋值给常量theSortedNumbers

因为返回值指定为(evens: [Int], odds: [Int]),所以编译器推断新创建的常量就是这个类型。最后把结果打印到控制台。

2.可空返回值类型

有时候我们想让函数返回可空实例(可以为空的实例)

如果一个函数在某些情况下返回nil 在其他情况下返回一个值的话,Swift提供了可空返回值以供使用

funcgrabMiddleName(fromFullName(外部参数名)name(内部参数名):(String,String?,String)元祖类型的参数)->String?{

returnname.1

元组是零索引的应该改成从零开始索引

}

letmiddleName=grabMiddleName(fromFullName:("Matt",nil,"Mathias"))

iflettheName(为真打印 不为真不打印)=middleName{

print(theName)

}

3.提前退出函数

guard语句

跟if/else

相同

根据表达式的布尔值来执行代码

不同

某些条件不满足 可以用guard语句来提前退出函数

防止代码在某种不当条件下运行

有中间名 就打印中间名 没有就执行默认值

func greetByMiddleName(fromFullName name:(元祖name中的元素有名字)(first:String,

middle:String?,

//(没有返回值)last:String)){

guardletmiddleName=name.middleelse(把name.middle绑定到middleName常量上 如果可空实例没有值 那么么guard else语句中的代码会执行){

print("Hey there!")

return (之后 用return从函数显示返回(提前返回显示出来))

}

print("Hey \(middleName)")

}

greetByMiddleName(fromFullName:("Matt","Danger","Mathias"))

可以把guard 语句想象成防止一下尴尬情况发生  我们不知道某人中间名的情况下只能函数应付过去

这意味着middleName在包围着gurad语句的父作用域中可见。

4.函数类型

每个函数都有特定的类型

所有的函数都有  函数类型由函数参数和返回值组成

以sortedEvenOddNumbers(_:)函数为例,它接受整数数组作为参数,返回有两个整数数组的元组。于是,sortedEvenOddNumbers(_:)的类型可以表示为:([Int]) -> ([Int], [Int])。

参数在左边圆括号  返回值在-> 后面

“一个接受整数数组作为参数并返回带有两个整数数组的元组的函数。”作为比较,既没有参数也没有返回值的函数类型是:() -> ()

函数类型实例话  在赋值给变量  函数本身也可以作为参数和返回值

letevenOddFunction:([Int])->([Int],[Int])=sortedEvenOddNumbers

这行代码创建了一个evenOddFunction 常量   其值是sortedEvenOddNumbers函数

通过常量 调用函数(函数也可以作为常量)

举个例子,evenOddFunction(numbers: [1,2,3])会把作为参数传递的数组中的数字放进有两个数组的元组中——一个数组放奇数,另一个放偶数。类似多个返回值提到的例子

你可能感兴趣的:(Swift编程权威指南(第2版)第 12 章 函数笔记)