Swift--方法(函数)
方法是执行特殊任务的自包含代码块。你可以给方法名字来表示它的功能,而且在需要的时候调用这个名字的方法来执行它的任务。
Swift方法的语法表达很灵活,从类似c的没有参数名的方法到oc复杂的带有名字和参数的方法。参数在简单方法的调用中可以提供默认的初始值,也可以传入一个变量的参数,当方法执行完后可以修改这个参数。
每个方法在Swift中都有一个类型,其中包括参数类型和返回类型。你可以享其他任何在Swift类型一样使用这些类型,它可以让方法更容易的为作为另外一个方法的一个参数值,从方法的返回值获取返回值。函数也可以写在其他的函数中,以便在嵌套的函数范围内封装有效的功能。
1.函数的声明与调用
当你定义一个函数的时候,你可能定义一个或者多个名字,函数的传入值的类型称为参数。你也可以选择定义一个方法执行后可能返回值的类行,称为返回值。
每个函数的名字最好能描述出它的功能。使用函数的时候,调用这个函数的名字并出入一个输入值(及我们所称的参数),这个参数的类型要与这个函数的参数类型一致。函数的参数必须始终以与函数的参数列表相同的顺序提供。
下面的例子定义了一个greet(person:),该函数输入一个人的名字,返回一个对这个人的问候字符串。为了实现这个例子,可以定义输入的参数,参数名为person、类型为String;以及返回一个String类型的返回值。
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
定义一个函数时把所有这些都组合一起,其中前缀用func 关键字。你定义函数返回值时用return的箭头“->”,后面跟着类型的名字返回。
这个函数的定义描述了它的功能是什么,接收什么参数,以及函数执行后返回的参数。这个定义可以让你在代码中任何地方更容易清楚的调用。
2.函数的参数与返回值
Swit函数中的参数和返回值是相当灵活的。你可以用从一个功能函数带一个没有命名的参数到 带有表达函数的参数和不同可选的参数的复杂函数定义一切。
(1)没有参数的函数
函数不需要定义输入参数。如下的这个函数没有带参数,每次调用该函数的时候,返回相同的字符串信息。
func sayHelloWorld() -> String {
return "hello, world"
}
print(sayHelloWorld())
// Prints "hello, world"
函数定义的时候仍然需要在函数名后面加上括号,尽管括号里面并没有参数。当函数调用的时候,函数名后面把空括号写上。
(2)函数带多个参数
函数可以带有多个输入参数,写在括号内,用“,”号分隔开。
func greet(person: String, alreadyGreeted: Bool) -> String {
if alreadyGreeted {
return greetAgain(person: person)
} else {
return greet(person: person)
}
}
print(greet(person: "Tim", alreadyGreeted: true))
// Prints "Hello again, Tim!"
(3)函数不带返回值
函数不需要定义一个返回类型。
func greet(person: String) {
print("Hello, \(person)!")
}
greet(person: "Dave")
// Prints "Hello, Dave!"
因为不需要返回一个值,这个函数在定义的时候不包含返回箭头(->)或者返回值。
注意:严格的说,greet(person: String)的函数也有返回值,尽管它的返回并没有定义。函数没有定义返回值的类型时通常返回的是一个特殊类型值Void。它是一个简单的空元组,可以用“()”表示。
调用一个函数的时候,它的返回值可以忽略。
func printAndCount(string: String) -> Int {
print(string)
return string.count
}
func printWithoutCounting(string: String) {
let _ = printAndCount(string: string)
}
printAndCount(string: "hello, world")
// prints "hello, world" and returns a value of 12
printWithoutCounting(string: "hello, world")
// prints "hello, world" but does not return a value
第一个方法 printAndCount(string:,打印一个字符串,然后返回Int类型的字符串个数。第二个方法
printWithoutCounting(string:)调用了第一个方法,但是忽略的它的返回值。当调用第二个函数的时候,第一个函数的信息依然打印,但是它的返回值并没有用到。
(4)函数带有多个返回值
你可以用元组的返回类型作为一个函数的多个返回值。
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)
}
minMax(array:)这个函数返回一个带有两个Int值的元组。
因为元组中的成员值被命名为函数返回值的一部分,它们可以通过点语法来获取到最小和最大值。
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
// Prints "min is -6 and max is 109"
注意:tuple的成员不需要在tuple从函数返回的时候被命名,因为它们的名称已经被指定为函数的返回类型的一部分。
(5)可选的元组返回值
如果从函数返回一个元组类型有可能是一个没有值的元组类型,你可以用一个可选的元组返回类型去表明这个元组可能为nil。你写一个可选的元组返回类型通过在元组类型的括号外加上一个“?”号,例如: (Int, Int)?或者(String, Int, Bool)?。
注意:一个可选的元组类型例如(Int,Int)?不同于(Int?, Int?)。对于可选元组类型,是整个元组类型 可选,不是元组内的每一个值可选。
为了解决空数组的安全,编写一个minMax(array:)函数,这个函数有一个可选元组返回值,当数组为空时,这个返回值为nil。
func minMax(array: [Int]) -> (min: Int, max: Int)? {
if array.isEmpty { return nil }
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(array:)这个方法的返回值是真的一个值还是一个nil。
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
}
// Prints "min is -6 and max is 109"
3.函数的参数标签和参数名称
每个函数的参数都有参数的标签和参数名称。参数标签在函数调用时很有用的。在函数的实现用方法名会用得到。通常,参数用它们的参数名作为它们参数标签。
func someFunction(firstParameterName: Int, secondParameterName: Int) {
// In the function body, firstParameterName and secondParameterName
// refer to the argument values for the first and second parameters.
}
someFunction(firstParameterName: 1, secondParameterName: 2)
所有的参数必须用不一样的名字。尽管,多个参数可能会有相同的参数标签,唯一的参数标签可以帮助你的代码更加易读。
(1)指定参数标签
你可以在参数名字面前写上参数标签,用 空格分隔开。
func someFunction(argumentLabel parameterName: Int) {
// In the function body, parameterName refers to the argument value
// for that parameter.
}
当下是一个关于greet:(person:)的方法,输入一个人的名字还有家乡,返回一个问候语:
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// Prints "Hello Bill! Glad you could visit from Cupertino."
标签的使用使得函数像表达式一样调用,类似于句子,同时还使得函数体更容易解读、更清晰。
(2)省略参数标签
如果你的参数不需要参数标签,用下划线代替参数的参数标签。
func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
// In the function body, firstParameterName and secondParameterName
// refer to the argument values for the first and second parameters.
}
someFunction(1, secondParameterName: 2)
如果一个参数有参数标签,当你调用函数的时候,参数必须被标记。
(3)默认参数值
你可以在函数中为任何的参数定义一个默认的值,通过在参数类型的后面为参数分配一个值。如果你设置了默认的值,当你调用函数的时候,可以省略参数。
func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
// If you omit the second argument when calling this function, then
// the value of parameterWithDefault is 12 inside the function body.
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault is 6
someFunction(parameterWithoutDefault: 4) // parameterWithDefault is 12
在函数的参数列表开始时,在具有默认值的参数之前,放置没有默认值的参数。没有默认值的参数通常对函数的意义更为重要——首先编写它们使识别相同的函数被调用变得更加容易,无论是否省略了默认参数。
(4)可变参数
一个可变的参数可以结束从0到其他更多指定类型的值。当函数调用的时候,你可以用可变参数指定可以输入参数的值。可变参数的实现是通过在参数名的后面插入三个省略号“...”。
传入可变参数的值在函数是有效地在函数体中以数组的形式存在。例如,一个可变参数名为numbers、类型为Double...在函数体作为一个名叫做numbers类型为[Double]数组常量存在的。
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)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers
注意:一个函数可能最多有一个可变参数。
(5)输入输出参数
函数的参数值通常都是默认的。尝试在函数体的内部改变一个函数的参数值会出现编译时错误。这就是意味着你不能错误地改变一个参数的值。如果你想要修改一个函数的参数值,而且在函数调用结束后仍然保持这个改变值,定义这个参数为in-out参数来替代。
你可以用在in-out参数中传入一个变量,你不能传入常量作为参数,因为常量是不可更改的。当你给in-out参数传入一个参数值时,在变量名前面用&符号,表明这个变量在函数中是可改变的。
注意:输入输出参数不能有默认值,可变参数不能标记为输入输出参数。
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
这个函数是两个值的交换,当你调用swapTwoInts这个方法是,传入2个Int类型的变量。当someInt和anotherInt值传入swapTwoInts时,前面带上&符号。
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Prints "someInt is now 107, and anotherInt is now 3"
注意:输入输出参数与函数定义的返回值时不同的。swapTwoInts的例子中没有定义一个返回值和返回类型,但它仍然修改了someInt和anotherInt的值。输入输出参数为函数在函数体的范围内改变输出值提供了另外一种选择。
5.函数类型
每个函数都有一个特定的函数类型,由参数类型和函数返回值类型组成。
例如:
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() {
print("hello, world")
}
这个函数的类型是:()->Void 或者一个方法没有参数,返回值为void。
(1)用函数类型
正如使用Swift中其他类型一样使用函数类型。例如,你可以定义一个常量或者变量为函数类型,并为这个变量分配一个合适的函数。
var mathFunction: (Int, Int) -> Int = addTwoInts
可以解读如下:
定义一个叫做 mathFunction 的变量,这个变量是 带有两个Int参数的函数并返回一个Int值的类型。让这个变量指向addTwoInts的函数。
你可以用mathFunction调用分配的函数。
print("Result: \(mathFunction(2, 3))")
// Prints "Result: 5"
不同的函数有相同的类型就可以分配给相同的变量,对于没有函数类型的也一样:
mathFunction = multiplyTwoInts
print("Result: \(mathFunction(2, 3))")
// Prints "Result: 6"
与其他类型类似,你可以让Swift推断函数类型,当你把一个函数复制给一个常量或者变量的时候。
let anotherMathFunction = addTwoInts
// anotherMathFunction is inferred to be of type (Int, Int) -> Int
(2)函数类型作为参数类型
你可以用函数类型例如(Int, Int)->Int 作为另外一个函数的参数类型。这使您能够在函数调用时为函数的调用方保留函数实现的某些方面。
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// Prints "Result: 8"
这个叫做printMathResult方法的例子,有是三个参数。第一个参数叫做mathFunction,它的类型是(Int, Int)->Int。你可以传入任何符合这个函数类型的函数。第二和第三个参数分别是a和b,两个的类型都是Int类型。
printMathResult(_:_:_)的作用是将调用的结果打印成合适类型的数学函数。函数的实现实际上并不重要——它只关系到函数的正确类型。这使printMathResult(_:_:_:)能够以类型安全的方式将其功能传递给调用者。
(3)函数类型作为返回值类型
你可以用一个函数类型作为另外一个函数的返回值类型。在一个函数的返回箭头(->)后面加上函数类型来实现。
func stepForward(_ input: Int) -> Int {
return input + 1
}
func stepBackward(_ input: Int) -> Int {
return input - 1
}
下面这个方法叫做 chooseStepFunction(backward:),它的返回类型是
(Int) -> Int。chooseStepFunction(backward:)函数根据backward的布尔值来判断是返回stepBackward函数还是返回stepForward函数。
6.嵌套函数
目前在本章节你所遇到的函数都是全部函数,它定义于全局范围。你可以在函数体中定义函数,也就是我们所说的嵌套函数。
默认情况下,嵌套函数隐藏在外部世界中,但仍然可以通过其封闭函数调用和使用。一个封闭函数还可以返回它的一个嵌套函数,允许在另一个范围内使用嵌套函数。
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!
Swift--方法(函数)的更多相关文章
- Swift(三.函数)
一.swift中的函数分为以下几类吧 1>无参无返 2>无参有返 3>有参无返 4>有参有返 5>有参多返 二.看下面几个例子吧 1>无参无返 func a ...
- Swift 语言函数
import Foundation // 函数声明于实现 func sayHello(name){ print("Hello \(name)") } // 函数调用 sayHell ...
- <经验杂谈>C#中一种最简单、最基本的反射(Reflection):通过反射获取方法函数
说起反射之前和很多用C#/.net的同仁们一样,相比于一般应用层对数据的增删改查总有点觉得深奥到难以理解.其实程序这东西,用过.实践过就很简单,我一直这么认为. 先说下概念:反射 Reflection ...
- Python学习入门基础教程(learning Python)--8.3 字典常用的方法函数介绍
本节的主要讨论内容是有关dict字典的一些常用的方法函数的使用和范例展示. 1. clear清除字典数据 语法结构如下: dict_obj.clear() 示例代码如下: dict1 = {'web' ...
- swift 之 函数
swift的函数跟脚本语言有很多神似之处. 如果有一天用swift开发服务器 ,很期待哇(一切皆有可能,毕竟人家说要跑在Linux上),
- PHP(方法 函数 循环 和 数组 查找)
循环 和 数组 查找 顺序查找 二分法查找 冒泡排序 方法 函数 定义:一堆代码的集合叫做函数(满足条件下“一堆”) 语法,定义,调用,参数列表(形参,实参),返回值 两种方法: function 方 ...
- Swift 中函数使用指南
关于Swift中的各种函数的使用的总结 前言 时间久了,好多东西我们就会慢慢忘记,在这里总结一下Swift中函数的使用原则,把大部分的函数使用技巧用代码示例来做了演示,但是如果想提高,还是要多多思考才 ...
- scala(一)方法&函数
写在前面 众所周知,scala一向宣称自己是面向函数的编程,(java表示不服,我是面向bean的编程!)那什么是函数? 在接触java的时候,有时候用函数来称呼某个method(实在找不出词了),有 ...
- OpenCV2:总结篇 工具方法函数
一.简介 OpenCV提供了一些工具方法函数来辅助完成图像运算 二.时间相关 1.getTickCount()和getTickFrequency() double tTime; tTime = (do ...
- C#学习笔记_06_方法&函数
06_方法&函数 方法的定义 方法就是一个功能的集合,可以把程序中某段具有特殊功能的代码提取出来: 声明方法 [ 访问权限修饰符 ] [ 其他的修饰符 ] 返回值类型 方法名 ( [形参列表] ...
随机推荐
- PMP项目管理学习笔记(9)——范围管理
关于范围管理的几个名词定义 产品范围:表示你和你的团队正在构建的产品或服务的特性和功能:产品范围与最终产品有关,包括产品的特性,组件和组成部分.人们谈论确定产品的范围时,大多都是在谈论确定产品的特性, ...
- UVA 11346 Probability 概率 (连续概率)
题意:给出a和b,表示在直角坐标系上的x=[-a,a] 和 y=[-b,b]的这样一块矩形区域.给出一个数s,问在矩形内随机选择一个点p=(x,y),则(0.0)和p点组成的矩形面积大于s的概率是多少 ...
- Windows各个文件夹介绍
windows文件介绍 总结 ├WINDOWS │ ├-system32(存放Windows的系统文件和硬件驱动程序) │ │ ├-config(用户配置信息和密码信息) │ │ │ └-system ...
- Using URL Schemes to Communicate with Apps
要素:1)通信双方:2)协议:3)支持机制(系统,进行协议注册):4)数据 https://developer.apple.com/library/content/documentation/iPho ...
- 浏览器报错 SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data at line 1 column 2 of the JSON data
ajax调用是200,结果返回的不是json字符串(字符串格式不是json应该有的格式),进入了ajax的error回调函数,改为返回json字符串,问题解决了.
- TWaver3D直线、曲线、曲面的绘制
插播一则广告(长期有效) TWaver需要在武汉招JavaScript工程师若干 要求:对前端技术(JavasScript.HTML.CSS),对可视化技术(Canvas.WebGL)有浓厚的兴趣 基 ...
- IFE春季班第一阶段任务(请仔细阅读)
第一阶段的主要目标是帮助大家 了解.认识.学习.掌握HTML及CSS.第一阶段任务从 3月14日 开始,持续到 4月3日.当然,您也可以在这个时间以后继续自行实践练习. 第一阶段任务一共有 12 个题 ...
- linux秘钥分发
秘钥分发 ssh-copy-id -i /root/.ssh/id_rsa.pub "-p 9000 root@192.168.1.100" 传送文件 scp -P9000 -rp ...
- consul无client模式
1.推consul的镜像到生产应用全部服务器. 每个consul的server模式的容器,都需要单独的物理服务器. 主节点:docker run -d --net=host --name=consul ...
- web即时通信技术
ajax jsonp polling setInterval定期发送ajax请求.服务器压力大,浪费流量,大部分是无效请求 ajax long polling ajax发起请求,服务器对于这个请求一直 ...