1.函数
1.1函数格局:
1).多个回来值时: func 函数名(参数名:参数类型, ...)-> (回来值类型, ...){}
2).单个回来值时: func 函数名(参数名:参数类型, ...)-> 回来值类型{}
3).无回来值时:func 函数名(参数名:参数类型, ...)-> ()
或func 函数名(参数名:参数类型, ...)-> Void
(Swift规范库界说:public typealias Void = ()
)
Tips:
1).形参默许是let,也只能是let;
2).完结函数多个回来值,运用的其实是Swift中的元组(Tuple)类型
1.2 参数初始值
参数设置初始值参数名称:参数类型 = 初始值
func person(name:String ,age : Int,job : String = "free worker"){
print("name = \(name),age = \(age),job = \(job)")
}
如上声明完函数后,在调用函数时能够看到:
由此可知:带有初始值的参数,在调用函数的时分能够给此参数传值,也能够不用给传值;
1.3 可变参数(Variadic Parameter)
格局为:参数名称:参数类型...
注意:
1).每个函数只能存在一个可变参数;
2).紧跟在可变参数后边的参数不能省掉参数标签
3).可变参数的参数名称能够运用省掉参数标签
4).省掉参数标签和可变参数类型相一起,不要连续声明,欠好差异入参给了哪个参数
func makeSentence(words : String...,other:String) -> String{
var sentence = ""
for word in words {
sentence = sentence + " " + word
}
sentence = sentence + other
return sentence
}
makeSentence(words: "Function","having", "Variadic parameters","Add as many strings here you want", "Can use one variadic parameter per func","Make full use",other:".")
1.4 参数标签(Argument Label)
能够修改参数标签;
1).参数标签格局为:func 函数名(参数标签 参数名:参数类型, ...)-> (回来列表){}
2).省掉参数标签格局:func 函数名(_ 参数名:参数类型, ...)-> (回来列表){}
此刻声明函数实例变量后,不显示参数名。
1.5 隐式回来(Implicit Return)
假如整个函数体是一个单一表达式,那么函数会隐式回来整个表达式,这时能够省掉return要害字。
举个:
func sum(v1 : Int, v2 : Int) -> Int{
v1 + v2
}
此刻sum
函数的函数体是:v1 + v2
;是一个单一表达式,能够省掉return
要害字。
1.6 函数重载(Function Overload)
函数重载规则:
1).函数名相同
2).参数个数不同 || 参数类型不同 || 参数标签不同
举个:
//原函数
func sum(v1:Int,v2:Int)-> Int{
v1 + v2
}
//参数标签不同
func sum(_ v1 : Int,_ v2 : Int) -> Int{
v1 + v2
}
func sum(a : Int,b : Int) -> Int{
a + b
}
//参数个数不同
func sum(v1:Int,v2:Int,v3:Int)-> Int{
v1 + v2 + v3
}
//参数类型不同
func sum(v1:Int,v2:Double) -> Double{
Double(v1) + v2
}
func sum(v1:Double,v2:Int)-> Double{
v1 + Double(v2)
}
Tips:回来值类型与函数重载无关
func sum(v1:Int,v2:Int) -> Int{v1+v2}
func sum(v1:Int,v2:Int){}
sum(v1:10,v2:20)//报错:Ambiguous use of sum(v1:v2)
上面回来值类型不同,不构成函数重载。
1.6 函数运用
函数类型由:形式参数类型、回来值类型组成
函数类型能够作为参数、回来值;
1.6.1 函数界说为变量、常量
举个:
//平方
func square(_ num : Int) -> Int{
return num * num
}
square(4)
//立方
func cube(_ num : Int) -> Int{
return num * num * num
}
cube(4)
//能够将函数,赋值给一个变量或常量,功能和作用与square相同
var exponentialFunction = square
exponentialFunction(4)
//打印成果:16
cube(exponentialFunction(4))
//打印成果:4092
1.6.2 函数作为入参
var integers = [1,2,3,4,5]
func sumOfExponentialsOf(array a: [Int], with function: (Int)->Int)->Int
{
var result = 0
for x in a
{
result = result + function(x)
}
return result
}
sumOfExponentialsOf(array: integers, with: exponentialFunction)
//打印成果:55
1.6.2 函数作为回来
回来值类型是函数的函数,称为高阶函数(Higher-Order Function)
1.6.3 嵌套函数(Nested Function)
将函数界说在函数内部,称为嵌套函数 举个:界说一个函数,函数回来值类型为函数,内部具有嵌套函数
func chooseComputation(isSquared b : Bool) -> (Int)->Int{
func square(_ num :Int)->Int//嵌套函数
{
return num*num
}
func cube(_ num :Int)->Int
{
return num*num*num
}
if b {
return square
}
else{
return cube
}
}
var result = chooseComputation(isSquared: true)//result是(Int)->(Int)类型的函数。
result(2) //打印成果:4
result = chooseComputation(isSquared: false)
result(2) //打印成果:8
let value = chooseComputation(isSquared: true)(5)//此刻value是Int类型,打印成果:25
2.结构体
在Swift中,绝大多数常见类型都是结构体,包含:Bool、Int、Double、String、Array、Dictionary等常见类型都是结构体。结构体有个几个显着特色:
特色1:一切结构体都有一个编译器主动生成的初始化器(initializer,初始化办法、结构器、结构办法).
struct Rectangle{
var width
var height
}
var rectangle = Rectangle.init(width: 10, height: 10)
特色2:编译器会依据情况,或许会为结构体生成多个初始化器,主旨是:保证一切成员都有初始值。 举个1:
struct Rectangle{
var width : Int = 10
var height : Int
}
//初始办法1:
var rectangle = Rectangle(width: 20, height: 20)
//初始办法2:
var rectangle2 = Rectangle(height: 10)
举个2:此刻width和height默许都是nil,相当于结构体成员变量都有值,所以不报错
struct Rectangle{
var width : Int?
var height : Int?
}
//初始办法1:
var rectangle = Rectangle(width: 20, height: 20)
//初始办法2:
var rectangle2 = Rectangle(height: 10)
//初始办法3:
var rectangle3 = Rectangle()
特色3:假如初始化的结构体为常量,即便结构体成员为变量,也不行更改
let rectangleConstant = Rectangle()
rectangleConstant.height = 20//报错
rectangleConstant.width = 20//报错
特色4:假如初始化的结构体为变量,结构体成员为常量,此刻结构体成员不行更改
struct Circle{
let radius : Int = 0
}
var circle = Circle()
circle.radius = 10//报错
特色4:一旦在界说结构体时自界说了初始化器,编译器就不会再为结构体主动生成其他初始化器。
3.类
1)、类结构:
class 类名 {}
2)、类界说和结构体类似,但编译器并没有为类主动生成能够传入成员值的初始化器。
3)、假如类的一切成员都在界说的时分指定了初始值,编译器会为类生成无参的初始化器。
4)、类的内存中分别存储了:指向类型信息(8字节)+ 引证计数(8字节)+变量;类中的办法不存储在类的内存中。
5)、类内存对齐系数为16。
4.结构体和类的差异
1)结构体是值类型(枚举也是值类型),类为引证类型(指针类型);
2)编译会主动为结构体生成初始化办法;类不会,类手动声明
3)结构体内存纷歧定在栈空间内,取决于结构体变量界说的位置,假如在函数中界说结构体变量,结构体变量内存在栈空间中。
4)声明的类变量是一个指针变量,指针指向堆中存储的类。类必定存在堆空间中,类变量纷歧定,取决于界说类变量的位置。
5.值类型&引证类型
5.1值类型
1)值类型赋值:给var、let或许给函数传参,是直接将一切内容复制一份,属于深复制(deep copy)
2) 为了提高功能,String、Array、Dictionary、Set采取了Copy On Write的技能。仅当有“写”操作时,才会真实履行复制操作。
3)值类型包含:枚举(Optional)、结构体(Bool、Int、Float、Double、Character)、Array、Dictionary、Set。
5.2引证类型
- class是引证类型
- 引证赋值给var、let或许给函数传参,是将内存地址复制一份,属于浅复制。
6.闭包
函数也是闭包的一种;闭包是没有姓名的函数,也没有func
要害字.
6.1闭包表达式
闭包表达式:
{ (参数列表) -> 回来值类型 in 函数体代码 }
附加:
1)当没有回来值时,或回来值类型能够从上下文推断出来,能够省掉回来值类型
部分;
2)当没有入参时,或入参类型能够从上下文推断出来时,能够省掉参数列表
部分的代码
6.2跟随闭包
跟随闭包是一个写在函数调用括号外面(后边)的闭包表达式。
map
、sorted
也是一种跟随闭包。
//将整数型数组转变为字符型数组
var numbersArray = [1,2,3,4,5,6]
var closureString = numbersArray.map{
return "\($0)"
}
print(closureString)//打印成果:["1", "2", "3", "4", "5", "6"]
//运用跟随闭包按降序摆放数组
var descendingArray = numbersArray.sorted{$0 > $1}
print(descendingArray)//打印成果:[6, 5, 4, 3, 2, 1]
6.3逃逸(转义)闭包
1)转义闭包:传入函数的闭包,在函数履行完毕之后才会被调用的。换句话说,它比传递给它的函数更长命。转义闭包通常用于完结处理程序,因为它们在函数完毕后被调用。
2)非转义闭包:传入函数的闭包,在函数履行中会被调用的,即在它回来之前。默许情况下,闭包是不行转义的,需要运用要害@escaping
润饰。
6.4主动闭包(@autoclosure)
主动闭包是一种主动创立的,用来把作为实践参数传递给函数的表达式打包的闭包。它不承受任何实践参数,并且当它被调用时,它会回来内部打包的表达式的值。
这个语法的好处在于通过写一般表达式替代显示闭包而使你省掉函数形式参数的括号。
举个:
//没有添加@autoclosure
func getFirstPositive(_ v1:Int,_ v2:()->Int) -> Int?{
return v1 > 0 ? v1 : v2()
}
getFirstPositive(-4) {20}
//添加@autoclosure后
func getFirstPositive(_ v1:Int,_ v2:@autoclosure ()->Int) -> Int?{
return v1 > 0 ? v1 : v2()
}
getFirstPositive(-4, 20)
附加:
@autoclosure只支持()-> T
格局的参数;
空合并运算符??运用了@autoclosure技能;
有@autoclosure、无@autoclosure,构成了函数重载;