2018-05-30
import UIKit
class FunctionController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//1 调用 实参传入的是空元组
voidFunc(v: ())
//2 调用
function(label: 10, label: 10)
//3 调用 (注意 编译错误: 缺失了第二个形参的实参)
// oops(10)
//4 调用
// 不传任何不定个数形参所对应的实参
foo(a: 0)
// 传了1个不定个数形参所对应的实参
foo(a: 0, b: 1)
// 传了3个不定个数形参所对应的实参
foo(a: 0, b: 1,2,3)
//5 调用
var b: Int! = nil
var c: Int! = 5
poo(a: &b)
poo(a: &c)
print("b = \(b)")
print("c = \(c)")
//6 调用
(foo as (Int?) -> Void)(2)
let _: Int = foo(2)
}
//1 定义一个具有Void类型形参返回类型为Void的函数
func voidFunc(v: Void) -> () {
}
//2 定义 实参可相同,形参必须不同
func function(label p1: Int, label p2: Int) {
print("parameter is: \(p1 + p2)")
}
//3 定义 实参都缺省且中间的参数不带默认值
func oops(_ a: Int = 1, _ b: Int, _ c: Int = 2) {
}
//4 定义一个带有Int类型的不定参数个数的函数foo
func foo(a: Int, b: Int...) {
var sum = a
if b.count > 0 {
for i in b {
sum += i
}
}
}
//5 定义一个Int!输入输出参数类型的函数
func poo(a: inout Int!) {
if a == nil {
a = 0
}else {
a! += 10
}
}
//6 定义两个重载函数(返回类型不同)
func foo(_ c: Int?) {
print("foo c = \(String(describing: c))")
}
func foo(_ g: Int?) -> Int {
return g ?? 0
}
}
- (1) 函数定义与调用
/// func 函数名 (函数形参列表) -> 返回类型 {函数体}
/// swift 的 形参类型 与 返回类型 可以是swift所支持的任一类型,数组,元组... - (2) 函数的实参/形参标签
/// 实参标签名可以相同 形参标签名必须各不相同
/// 实参可缺省 形参如函数体内不使用也可缺省 用通配符 _
/// 从swift4.0起,调用形参类型为Void类型的函数时,对应的实参必须显示传入空元祖,即() - (3) 默认形参值 (无需放在形参列表的最后,跟c++不同)
/// 在调用一个带有默认形参值得函数时,倘若使用该新参的默认值,那么连它的实参标签都不需要写,实参标签加上实参值全都缺省 - (4) 不定个数的形参(无需放在形参列表的最后)
/// ...前面跟一个类型
/// 可以把它视作为它所指定类型的数组 通过count属性获取实参所传递过来的参数个数,通过下表操作符来获取对应的实参值 - (5) 输入输出形参 in-out parameters
/// 在swift中,所有新参默认都是常量
/// 当我们调用一个函数时,对其中某一个输入输出形参传递了某个实参,在该函数内会做以下三步:
/// 1,当函数在调用前,先将实参的值拷贝到所对应的输入输出形参中
/// 2, 在执行函数中的代码时,对输入输出形参的值进行修改
/// 3, 在函数返回之后,将修改后输入输出形参的值拷贝回对应的实参中
/// 关键字 in-out 仅仅只是个类型限定符,用于描述当前形参在该函数体内可被修改而已
/// “而在调用函数时,我们在表示实参的表达式之前加上 & 单目前缀操作符,表示该实参将会在函数返回后被所对应的形参进行赋值。 单目前缀操作符 & 的操作数必须是一个变量,而不能是一个常量”
/// 输入输出参数类型的匹配比一般的要求更为严苛,inout Int! 与 inout Int? 作为不兼容的参数类型 - (6) 函数重载
/// 函数重载的判断依据为形参个数、形参类型以及函数的返回类型,其实还有实参标签的区别(这个跟函数签名有关)
/// 如果仅仅是函数返回类型不同,那么调用的时候难以判别当前所调用的是哪个函数,因此需要使用as投射操作符将函数标识显示转换为特定的函数类型进行调用;或者对左值对象显式标注类型来告诉编译器,此时应该调用哪个类型的函数。不过,为了避免这种麻烦,一般使用不同的实参标签来更好得加以区分 - (7) 函数类型与函数签名 (理解好概念) (1: 函数引用对象相关概念 2: 函数签名表达式相关概念)
/// 1 声明一个函数引用对象的时候,其函数形参类型不能带有实参标签 (实际是声明)
/// 1 调用一个函数引用对象的时候,它所指向的函数实体(实际是调用,就是函数签名表达式后面括号调用,即是实参不用了)已经是确定的了,所以不需要使用实参标签(也不允许给出),因为实参标签属于函数签名的一部分,用于标识一个特定的函数实体,而函数类型本身就是一个纯粹的类型,因此不需要,和带标签的元组不同。
/// 1 而且这个指向函数的引用对象类型(实际也就是一个函数签名表达式)的函数形参中不能含有形参标签。
/// (注意)一个指向函数的引用对象 与 其它类型的对象一样 闭包是引用类型。函数也是,跟类类型一样
/// 2 一个函数签名表达式就已经表征了一个指向它所表示的函数的引用,所以该表达式的类型就是一个函数类型
/// 2 在通过函数签名表达式去做函数调用时,也不需要显式给出实参标签,并且也不允许给出
/// 2 严格意义上,两个具有不同函数签名的函数就已经表征了其不同的实体,(这里所描述的是实参标签不同或函数名不同,但是如果函数签名全都相同,那么再去判定那两个函数的类型)也就是用 as 投射操作符 - 8 嵌套函数定义 (nested functions)
/// 嵌套函数会持有外部函数的局部对象
/// 嵌套函数不仅可以直接定义在函数体内,而且还能定义在语句块作用域内 - 9 统一的函数引用体系
/// 一个函数类型引用对象可以指向函数、闭包、实例方法三者任意一种
网友评论