Swift 学习- 07 -- 函数
// 函数
// 函数是一段完成特定任务的独立代码片段, 你可以通过给函数命名来标识某个函数的功能, 这个名字可以被用来在需要的时候'调用'这个函数来完成它的任务
// swift 统一的函数语法非常的灵活, 可以用来表示任何函数, 包括从简单的没有参数名字的 C 风格函数, 到复杂的带局部的外部参数 OC 风格函数, 参数可以提供默认值, 以简化函数调用, 参数也可以即当做传入参数, 也当做传出参数,也就是说, 一旦函数执行结束, 传入的参数值会被修改
// 在 swift 中, 每个参数都有一个由函数的参数值类型和返回值类型组成的类型, 你可以把函数类型当做任何其它普通变量类型一样处理,这样就可以更简单地把函数当做别的函数的参数,也可以从其它函数中返回函数, 函数的定义可以写在其它函数的定义中,这样可以在嵌套函数范围内实现功能封装.
// 函数的定义与调用
// 当你定义一个函数时, 你可以定义一个或多个有名字和类型的值, 作为函数的输入, 称为参数, 也可以定义某种类型的值作为函数执行结束时的输出, 称为返回类型
// 每个函数有个函数名, 用来描述函数执行的任务, 要使用一个函数时, 用函数名来调用这个函数, 并传给它匹配的输入值(称作 实参), 函数的实参必须与函数参数里参数的顺序一致
func greet(person: String) -> String{
let greeting = "hello," + person + "!"
return greeting
}
// 函数的定义, 以 func 作为前缀, 指定函数返回类型时, 用返回箭头 -> (一个连字符后面跟一个右尖括号) 后跟返回类型的名称方式来表示
// 该定义描述了函数的功能, 它期望接收什么作为参数和执行结束时它返回的结果是什么类型
print(greet(person: "ahhh"))
// 注意 : prient(_:separator:terminator:) 函数的第一个参数并没有设置一个标签, 而其它的参数因为有了默认值, 因此是可选的
func greenAgain(person: String) -> String{
return "hello," + person + "!"
}
print(greenAgain(person: "houdehcneg"))
// 函数的类型与返回值
// 函数参数与返回值在 swift 中非常的灵活, 你可以定义任何类型的函数, 包括从只带一个未命名参数的简单函数到复杂的带有表达式参数名和不同参数选项的复杂函数
// 无参数函数
// 函数可以没有参数,
func sayHelloWorld() -> String{
return "Hello,World!"
}
print(sayHelloWorld())
// 尽管这个函数没有参数,但是定义中在函数名后还是需要一堆圆括号, 当被调用时,也需要在函数名写一对圆括号
// 多参数函数
// 函数可以有多种输入参数, 这些参数被包含在函数的括号内, 以逗号分隔
func greet(person: String,alreadyGreeted: Bool) -> String{
if alreadyGreeted {
return greenAgain(person: person)
}else{
return greet(person: person)
}
}
print(greet(person: "timw", alreadyGreeted: true))
// 无返回值函数
// 函数可以没有返回值, 下面是 greet(person:)函数的另一个版本,这个函数 直接打印一个 String值, 而不是返回它:
func greet2(person: String){
print(person)
}
// 因为这个函数不需要返回值, 所以函数的定义中没有返回箭头 (->) 和返回类型
// 注意 : 严格上来说, 虽然没有返回值被定义, greet(person:) 函数依然返回了值,没有定义返回值的函数会返回一个特殊的 Void 值, 它其实是一个空的元组, 没有任何元素, 可以写成 ()
// 注意 : 返回值可以被忽略, 但是定义了有返回值的函数必须返回一个值, 如果在函数定义底部没有返回任何值, 将导致编辑错误
// 多重返回值函数
// 你可以用元组 (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(array: [8,-5,2,109,-21,71])
print("min is \(bounds.min) ,max is \(bounds.max)")
// 需要注意的是, 元组的成员不需要在元组从函数中返回,因为它们的名字已经在函数的返回类型中指定了
// 可选元组返回类型
// 如果函数返回的元组类型有可能整个元组都 '没有值', 你可以使用可选的 (optional) 元组返回类型反映整个元组可以为 nil 的事实, 你可以通过在元组类型的右括号后放置一个问号来定义一个可选元组,例如 (Int,Int)?
// 注意 : 可选元组类型如 (Int,Int)? 与元组包含可选类型如 (Int?,Int?)是不同的, 可选的元组类型,整个元组是可选的, 而不是元组中的某个元素值
// 前面的例子 minMax(array:) 函数返回了一个包含两个 Int 值的元组,但是函数不会对传入的数组执行任何检查,如果传入的 Array 参数是一个空数组,会触发运行时错误,为了安全地处理这个空数组问题, 将 minMax(array:) 函数改写成可选元组的返回类型, 并且当数组为空时返回 nil
func minMax2(array: [Int]) -> (min: Int,max:Int)?{
if array.isEmpty {
return nil
}else{
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)
}
}
// 你可以用可选绑定来检查 minMax2(array:) 函数返回的是一个存在的元组还是 nil
if let bounds2 = minMax2(array: [8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
}
// 函数参数标签和参数名称
// 每个函数参数都有一个参数标签 以及 一个参数名称, 参数标签在调用函数的时候使用,调用的时候需要将函数的参数标签写在对应的参数前面, 参数名称在函数的实现中使用 , 默认情况下,函数参数使用参数名称作为衙门的参数标签
// 所有的参数都必须有独一无二的名字,
// 指定参数标签
// 你可以在函数名称前指定它的参数标签, 中间已空格分割
func someFunction(argumentlabel arameterName: Int){
print(arameterName)
}
someFunction(argumentlabel: 5)
// 忽略参数标签
// 如果你不希望某个参数添加一个标签, 可以使用一个下划线(_)来代替一个明确的参数标签
func someFunction2(_ firstParameterName:Int, seconedParamerer:Int){
print(firstParameterName + seconedParamerer)
}
someFunction2(8, seconedParamerer: 8)
// 如果一个参数有一个标签, 那么在调用的时候必须使用标签来标记这个参数
// 默认参数值
// 你可以在函数体中通过给参数赋值来任意一个函数的参数定义默认值 (Deafult Value), 当默认值被定义后,调用这个函数是可以忽略这个参数
func someFunction3(parameterWithoutDefault:Int,parameterWithDefault:Int = 12){
print(parameterWithDefault + parameterWithoutDefault)
}
someFunction3(parameterWithoutDefault: 8, parameterWithDefault: 8)
someFunction3(parameterWithoutDefault: 8)
// 将不带有默认值的参数放在函数参数列表的最前面, 一般来说, 没有默认值的参数更加的重要, 将不带有默认值的参数放在最前面保证在函数调时,非默认参数的顺序是一致的,同事也使得相同的函数在不同的情况下调用时显得更为清晰
// 可变参数
// 一个可变参数 可以接受 0 个 或者多个值, 函数调用时,你可以用可变参数来指定函数参数可以被传入的不确定数量的输入值, 通过在变量类型后面加(...)的方式来定义可变参数
// 可变参数的传入值在函数体中变为次类型的一个数组,
func arithmeticMean(_ numbers:Double...) -> Double{
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
print(arithmeticMean(45.4,78.5,96.2,151,151,2551,96.58))
// 注意 : 一个函数最多可以拥有一个可变参数
// 输入输出参数
// 函数参数默认是常量, 试图在函数体中更改参数值将会导致编辑错误.这意味着你不能错误地更改参数值,如果你想要一个函数可以修改参数的值, 并且想要在这些修改函数调用结束后仍然存在,那么就应该把这个参数定义为输入输出函数
// 定义一个输入输出函数时,在参数定义前加 inout 关键字, 一个 输入输出参数 有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值,
// 你只能传递变量给输入输出参数,你不能传入常量或者字面量,因为这些量是不能被修改的,当传入的参数作为输入输出参数时,需要在参数名前加 & 符, 表示这个值可以被函数修改
// 注意 : 输入输出参数不能有默认值, 而且可变参数不能用 inout 标记
func swapTwoInts(_ a: inout Int,_ b: inout Int){
let temporaryA = a
a = b
b = temporaryA
}
// 调用
var someInt = 3
var antherInt = 107
swapTwoInts(&someInt, &antherInt)
print("a is :\(someInt), b is :\(antherInt)")
// 从上面的例子中,我们可以看到 someInt 和 antherInt 的原始值在 swapTwoInts(_:_:) 函数中被修改,尽管它们的定义在函数体外
// 注意 : 输入输出参数和返回值不一样的,上面的swapTwoInts 函数并没有定义任何返回值,但仍然修改了 someInt 和 anotherInt 的值, 输入输出参数是函数对函数体外产生影响的另一种方式
// 函数类型
// 每个函数都有特定的函数类型, 函数的类型有函数的参数类型和返回值类型组成
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 类型的值'
// 使用函数类型
// 在 swift 中,使用函数类型就像使用其他类型一样, 例如, 你可以定义一个类型为函数的常量或变量, 并将适当的函数赋值给它
var mathFunction: (Int,Int) ->Int = addTwoInts(_:_:)
// 这段代码可以理解为. 定义一个叫做mathFunction 的变量,类型是'一个有两个 Int 类型的参数 并返回每一个 Int 类型的值的函数', 并让这个新变量指向 addTwoInts 函数
// mathFunction 和 addTwoInts 有同样的类型, 所以这个赋值过程在 Swift 类型检查(type-check)中是允许的
// 现在你可以用 mathFunction 来调用赋值的函数
print("Result: \(mathFunction(2,5))")
// 有相同匹配类型的不同函数可以被赋值给同一个变量, 就像非函数类型的变量一样
mathFunction = multiplyTwoInts(_:_:)
print("Result: \(mathFunction(5,8))")
// 就像其他类型一样,当赋值一个函数给常量或者变量时,你可以让 swift 来推断其函数类型
let antherMathFunction = addTwoInts
// antherMathFunction 被推断为 (Int,Int) ->Int 类型
// 函数类型作为参数类型
// 你可以用 (Int, Int) -> Int 这样的函数类型作为另一个函数的参数类型, 这样你可以将函数的一部分实现留给函数的调用者来提供
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int){
print("Result: \(mathFunction(a,b))")
}
printMathResult(addTwoInts(_:_:), 8, 5)
// 这个例子定义了printMathResult(_:_:_:)函数, 它有三个参数, 第一个参数叫 mathFunction, 类型是 (Int, Int) -> Int, 你可以传入任何这种类型的函数, 第二个和第三个参数叫做 a 和 b ,他们的类型是 Int, 这两个值作为已给出的函数的输入值
// 当 printMathResult(_:_:_:) 被调用时,它被传入 addTwoInts 函数和整数 a 和 b ,它用传入的 a 和 b 来调用 addTwoInts(_:_:), 并输出结果
// printMathResult(_:_:_:) 函数的作用就是输出另一个适当类型的数学函数的调用结果, 它不关心传入函数是如何实现的.只关心传入的函数是不是一个正确的类型,这使得 printMathResult(_:_:_:) 能以一种类型安全 (type-safe)的方式将一部分功能转给调用者实现
// 函数类型作为返回类型
// 你可以用函数类型作为另一个函数的返货类型, 你需要做的是返回箭头 (->) 后写一个完整的函数类型
// 下面的这个例子中定义了两个简单的函数, 这两个函数的类型都是 (Int) -> Int
func stepForward(_ input: Int) -> Int{
return input + 1
}
func stepBackward(_ input: Int) -> Int{
return input - 1
}
// 下面的函数的返回类型是 (Int) -> Int 类型的函数,
func chooseStepFunction(backward: Bool) -> (Int) -> Int{
return backward ? stepBackward(_:) : stepForward(_:)
}
// 你可以用 chooseStepFunction(backward:) 来获取两个函数其中的一个
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
print(moveNearerToZero(currentValue))
// 嵌套函数
// 到目前为止本章中你所见到的所有函数都叫做全局函数 (global functions), 它们定义在全局域中,你也可以把函数定义在别的函数体中, 称作 嵌套函数(nested functions)
// 默认情况下,嵌套函数是对外界不可见的, 但是可以被它们的外围函数 (enclosing function) 调用, 一个外围函数也可以返回它的某一个嵌套函数, 使得这个函数可以在其他域中被使用
// 你可以用返回嵌套函数的方式重写 chooseStepFunction(backward:)函数
func chooseStepFunction2(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 currentValue2 = -4
let moveNearerToZero2 = chooseStepFunction(backward: currentValue > 0)
print(moveNearerToZero2(currentValue2))
Swift 学习- 07 -- 函数的更多相关文章
- Swift学习之函数和简单地控件的创建
今天还是重复昨天做的事情--敲代码,但唯一的不同就是所学的知识不同了,我们又进一步往深得层次学习了,感觉越来越有意思了,虽然临近结束了看着大家积极性越来越低了,但是我知道我不能这样,我要比别人付出的 ...
- Swift学习笔记 - 函数与闭包
import Foundation //1.函数的定义与调用//以 func 作为前缀,返回箭头 -> 表示函数的返回类型func sayHello(name: String) -> St ...
- Swift 学习笔记 (函数)
函数 函数是一个独立的代码块,用来执行特定的任务.Swift中的函数与Object-C中的函数一样,但是声明与书写的方式不太一样,现在我们就通过几个例子介绍一下Swift中的函数.简单的来说,他与JS ...
- swift swift学习笔记--函数和闭包
使用 func来声明一个函数.通过在名字之后在圆括号内添加一系列参数来调用这个方法.使用 ->来分隔形式参数名字类型和函数返回的类型 func greet(person: String, day ...
- Swift 学习一函数&函数属性&懒加载
函数 函数相当于OC中的方法 格式: func 函数名(参数列表) -> 返回值类型 { 代码块 return 返回值} func 函数名(参数列表){ // 返回值为Void 可 ...
- Swift学习笔记(7):函数
目录: 函数参数与返回值 参数标签和参数名称 可变参数 传入传出参数 函数类型 嵌套函数 函数是一段完成特定任务的独立代码片段,使用func标示函数名,使用->标示返回类型. ・可以为函数参数设 ...
- 【Swift学习】Swift编程之旅---函数(十)
函数是一组用于执行特定任务的独立的代码段,你用一个名字来标识函数,这个名字是用来“调用”函数来执行它的任务. swift统一函数的语法具有足够的灵活性来表达任何一个简单的不带参数的名称与本地和外部的每 ...
- Swift学习——A Swift Tour 函数
Functions and Closures 函数和封闭性(闭包) Functions 函数的使用 Swift中的函数定义和OC中有明显的差别了,使用func定义函数,在括号里定义參数和类型,用 ...
- iOS ---Swift学习与复习
swift中文网 http://www.swiftv.cn http://swifter.tips/ http://objccn.io/ http://www.swiftmi.com/code4swi ...
随机推荐
- SQL Server2012远程访问第二个实列
现在有一台A电脑和一台B电脑,A是公司的服务器,安装了两个数据库实例(Sql Server 2012 和Sql Server2008 R2),B电脑在家,安装了Sql Server数据库两台电脑不在一 ...
- PHP中关于PDO数据访问抽象层的功能操作
PDO:数据访问抽象层 具有三大特点: 1.可以访问其它数据库 所有数据库都可以 2.具有事务功能 3.带有预处理语句功能(防止SQL注入攻击) 实例操作代码如下: <?php //1.造PD ...
- kindeditor编辑器上传图片
使用的是asp.net MVC 上传图片. 1.下载Kindeditor的对应的包 2.html页面 @{ Layout = null; } <!DOCTYPE html> <htm ...
- luogu P4916 魔力环
传送门 表示这种\(Burnside\)定理之类的东西一用就忘qwq 题目要求不同染色方案数,因为变换方式只有旋转,所以只有\(n\)个置换,然后可能会出现某种方案有循环节,这个循环节长度显然要是\( ...
- JDK1.8HashMap源码解读
package java.util; import sun.misc.SharedSecrets; import java.io.IOException; import java.io.Invalid ...
- Python 的异步 IO:Asyncio 简介
转载自https://segmentfault.com/a/1190000008814676 好文章 所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时, ...
- linux 日志管理
- 【Convex Optimization (by Boyd) 学习笔记】Chapter 2 - Convex sets(1) 仿射集&凸集
I. 仿射凸集(Affine and convex sets) 1. 线与线段 假设\(R^n\)空间内两点\(x_1,x_2\, (x_1≠x_2)\),那么\(y=\theta x_1+(1-\t ...
- python初级实战-----主机在线情况监控web
背景 公司有600多台服务器,打算写一个小程序,能一眼看见哪些服务器不在线. 大体思路是: 1.把所有服务器ip存进数据库,ping命令判断服务器是否在线 2.更新数据库中ip的状态 3.简单的web ...
- QR二维码原理(一)
一.什么是QR码 QR码属于矩阵式二维码中的一个种类,由DENSO(日本电装)公司开发,由JIS和ISO将其标准化.QR码的样子其实在很多场合已经能够被看到了,我这还是贴个图展示一下: 这个图如果被正 ...