闭包表达式
func sum(v1:Int,v2:Int) -> Int {
return v1 + v2
}
//转换到闭包表达式
var fn = {
(v1:Int,v2:Int)->Int in
v1 + v2
}
//调用
fn(1,3)
let fn = {
(v1:Int,v2:Int)->Int in
v1 + v2
}(10,20)
print(fn)
//只要编译器可以推断出来类型,就可以简写
func sum(v1:Int,v2:Int) -> Int {
return v1 + v2
}
func bigSum(v1:Int,v2:Int,v3:(Int,Int)->Int)-> Int{
return v3(v1,v2)
}
let dd = bigSum(v1: 5, v2: 8, v3: sum(v1:v2:))
//用闭包表达式去简写函数
let less = bigSum(v1: 20, v2: 10, v3: {$0 + $1})
//甚至简写
let lessS = bigSum(v1: 20, v2: 10, v3: +)
结构公式
{
(参数列表)->返回值类型 in
函数体代码
}
尾随闭包
- 如果一个闭包表达式作为函数的最后一个实参,那就可以使用尾随闭包
- 它是一个被书写在函数调用括号外面的闭包表达式
自动闭包
- @autoclosure 只支持()->T格式的参数
- 并不是只支持最后参数
- 空合并运算符运用了 @autoclosure自动闭包,自动封装
- 可实现延迟执行函数
//如果v1满足条件就不用v2了,相当于v2延迟加载
func autoFn(_ v1:Int,_ v2:@autoclosure ()->Int) -> Int {
return v1>10 ? v1 : v2()
}
let kk = autoFn(6,88) //88会自动封装成闭包
print(kk)
属性
- 存储属性
- 相当于成员变量
- 存储在实例的内存
- 结构体struct、类class都可以定义存储属性
- 枚举没有
- 在创建类或 结构体实例时 ,必须要为所有的存储属性设置一个合适的初始值(通过初始化器或直接定义)
- 计算属性
- 本质就是方法(函数)
- 不占用实例内存
- 枚举、结构体、类都可以定义计算属性
- 定义用 var,不能用let
- 属性观察器
- 初始化器设置属性值 不会触发willSet和didSet
- 在属性定义时设置初始值也不会触发willSet和didSet
- 利用类型属性去创建单例
inout本质
如果实参有物理内存地址,且没有设置属性观察器
- 直接将实参的内存地址传入函数(实参进行引|用传递)
如果实参是计算属性或者设置了属性观察器
- 采取了Copy In Copy Out的做法
- 调用该函数时,先复制实参的值,产生副本[get]
- 将副本的内存地址传入函数(副本进行弓|用传递) , 在函数内部可以修改副本的值
- 函数返回后,再将副本的值覆盖实参的值[ set]
- 总结: inout的本质就是引用传递(地址传递)
mutating
结构体struct、枚举enum是值类型,默认情况下其属性不能让自身的实例方法修改,但加上 mutating 可以允许这种行为 (下标除外)
struct Point {
var x = 0.0 , y = 0.0
mutating func edit(xx:Double,yy:Double){
x = xx
y = yy
}
}
@discardableResult 从此不再提醒你未使用返回值
下标subscript
- 可以给枚举、类、结构体,增加下标功能
- 本质就是方法(函数)
struct Point {
var x = 0.0 , y = 0.0
subscript (_ index:Int)->Double{
set{
if index==0 {
x = newValue
}else if index==1 {
y = newValue
}
}
get{
return index==0 ? x : y
}
}
}
var pp = Point()
pp[0] = 6.0
pp[1] = 10.0
print(pp[0],pp[1])
继承
- 值类型(枚举、结构体)不支持
- 类支持
- 没有父类的类 ,称为:基类
重写
- 子类可以重写父类的下标、方法、属性,重写时加上 override 关键字
- 被 static 修饰的类型方法、下标,不允许被重写 (可以换成class)
- 只能重写 var,不能 let
- 子类重写后的属性权限 不能 小于 父类属性权限
典型的重写实例属性范例
为父类增加属性观察器
- 除了只读计算属性、let,都可以增加属性观察器
final
- 被修饰过的方法、下标、属性,禁止被重写
- 被修饰的类,禁止被继承
协议Protocol
- 可以被枚举、结构体、类 去遵守
- 协议定义方法时不能有默认参数值
- 定义属性时必须用 var
- 实现协议时的属性权限要不小于协议中定义的属性权限
- 只有将协议中实例方法标记为 mutating
- 才能允许结构体、枚举的实现跨越修改自身内存
- 类的实现方法可以不用加 mutating
泛型generics
自己查吧,比较简单明了
关联类型Associated Type
- 给协议中用到的类型定义一个占位名称
- 可以拥有多个关联类型
- 或者直接给关联类型设定真实类型 : **typealias** Element = String
对于可选项的实现
//方法一:用objc的 optional
@objc protocol WUProtocol{
func oneFunc()->(Int)
func twoFunc()
@objc optional func threeFunc() ->()
}
class Yu: WUProtocol {
func oneFunc() -> (Int) {
return 88
}
func twoFunc() {
}
}
//方法二:用extension
protocol SomeProtocol {
func requiredFunc()
func optionalFunc()
}
extension SomeProtocol {
func optionalFunc() {
print("Dumb Implementation")
}
}
class SomeClass: SomeProtocol {
func requiredFunc() {
print("Only need to implement the required")
}
}
访问控制
模块区分权限
- open :允许其他模块访问,允许其他模块进行继承、重写(open只能用于类、类成员)
- public : 允许其他模块访问,不允许继承、重写
- internal :只允许当前模块中访问,不允许其他模块访问 (绝大部分实体都默认为 internal )
- fileprivate :只允许当前实体的源文件中访问
private : 只允许在定义实体的封闭声明中访问
enum不能为case单独设置访问级别