闭包表达式

  1. func sum(v1:Int,v2:Int) -> Int {
  2. return v1 + v2
  3. }
  4. //转换到闭包表达式
  5. var fn = {
  6. (v1:Int,v2:Int)->Int in
  7. v1 + v2
  8. }
  9. //调用
  10. fn(1,3)
  11. let fn = {
  12. (v1:Int,v2:Int)->Int in
  13. v1 + v2
  14. }(10,20)
  15. print(fn)
  16. //只要编译器可以推断出来类型,就可以简写
  17. func sum(v1:Int,v2:Int) -> Int {
  18. return v1 + v2
  19. }
  20. func bigSum(v1:Int,v2:Int,v3:(Int,Int)->Int)-> Int{
  21. return v3(v1,v2)
  22. }
  23. let dd = bigSum(v1: 5, v2: 8, v3: sum(v1:v2:))
  24. //用闭包表达式去简写函数
  25. let less = bigSum(v1: 20, v2: 10, v3: {$0 + $1})
  26. //甚至简写
  27. let lessS = bigSum(v1: 20, v2: 10, v3: +)

结构公式

  1. {
  2. (参数列表)->返回值类型 in
  3. 函数体代码
  4. }

尾随闭包

  • 如果一个闭包表达式作为函数的最后一个实参,那就可以使用尾随闭包
  • 它是一个被书写在函数调用括号外面的闭包表达式

image.png

自动闭包

  • @autoclosure 只支持()->T格式的参数
  • 并不是只支持最后参数
  • 空合并运算符运用了 @autoclosure自动闭包,自动封装
  • 可实现延迟执行函数
  1. //如果v1满足条件就不用v2了,相当于v2延迟加载
  2. func autoFn(_ v1:Int,_ v2:@autoclosure ()->Int) -> Int {
  3. return v1>10 ? v1 : v2()
  4. }
  5. let kk = autoFn(6,88) //88会自动封装成闭包
  6. print(kk)

属性

  • 存储属性
    • 相当于成员变量
    • 存储在实例的内存
    • 结构体struct、类class都可以定义存储属性
    • 枚举没有
    • 在创建类或 结构体实例时 ,必须要为所有的存储属性设置一个合适的初始值(通过初始化器或直接定义)
  • 计算属性
    • 本质就是方法(函数)
    • 不占用实例内存
    • 枚举、结构体、类都可以定义计算属性
    • 定义用 var,不能用let

image.png

  • 属性观察器
    • 初始化器设置属性值 不会触发willSet和didSet
    • 在属性定义时设置初始值也不会触发willSet和didSet

image.png

  • 利用类型属性去创建单例

image.png

inout本质

  • 如果实参有物理内存地址,且没有设置属性观察器

    • 直接将实参的内存地址传入函数(实参进行引|用传递)
  • 如果实参是计算属性或者设置了属性观察器

    • 采取了Copy In Copy Out的做法
    • 调用该函数时,先复制实参的值,产生副本[get]
    • 将副本的内存地址传入函数(副本进行弓|用传递) , 在函数内部可以修改副本的值
    • 函数返回后,再将副本的值覆盖实参的值[ set]
  • 总结: inout的本质就是引用传递(地址传递)

mutating

结构体struct、枚举enum是值类型,默认情况下其属性不能让自身的实例方法修改,但加上 mutating 可以允许这种行为 (下标除外)

  1. struct Point {
  2. var x = 0.0 , y = 0.0
  3. mutating func edit(xx:Double,yy:Double){
  4. x = xx
  5. y = yy
  6. }
  7. }

@discardableResult 从此不再提醒你未使用返回值

**

下标subscript

  • 可以给枚举、类、结构体,增加下标功能
  • 本质就是方法(函数)
  1. struct Point {
  2. var x = 0.0 , y = 0.0
  3. subscript (_ index:Int)->Double{
  4. set{
  5. if index==0 {
  6. x = newValue
  7. }else if index==1 {
  8. y = newValue
  9. }
  10. }
  11. get{
  12. return index==0 ? x : y
  13. }
  14. }
  15. }
  16. var pp = Point()
  17. pp[0] = 6.0
  18. pp[1] = 10.0
  19. print(pp[0],pp[1])

继承

  • 值类型(枚举、结构体)不支持
  • 类支持
  • 没有父类的类 ,称为:基类

重写

  • 子类可以重写父类的下标、方法、属性,重写时加上 override 关键字
  • 被 static 修饰的类型方法、下标,不允许被重写 (可以换成class)
  • 只能重写 var,不能 let
  • 子类重写后的属性权限 不能 小于 父类属性权限

存储属性、计算属性 —》 计算属性(不能重写为存储属性)

典型的重写实例属性范例

image.pngimage.png
调用顺序
image.png

为父类增加属性观察器

  • 除了只读计算属性、let,都可以增加属性观察器

image.png

final

  • 被修饰过的方法、下标、属性,禁止被重写
  • 被修饰的类,禁止被继承

协议Protocol

  • 可以被枚举、结构体、类 去遵守
  • 协议定义方法时不能有默认参数值
  • 定义属性时必须用 var
  • 实现协议时的属性权限要不小于协议中定义的属性权限
  • 只有将协议中实例方法标记为 mutating
    • 才能允许结构体、枚举的实现跨越修改自身内存
    • 类的实现方法可以不用加 mutating

image.png

泛型generics

自己查吧,比较简单明了

关联类型Associated Type

  • 给协议中用到的类型定义一个占位名称
  • 可以拥有多个关联类型

image.pngimage.png

  • 或者直接给关联类型设定真实类型 : **typealias** Element = String

对于可选项的实现

  1. //方法一:用objc的 optional
  2. @objc protocol WUProtocol{
  3. func oneFunc()->(Int)
  4. func twoFunc()
  5. @objc optional func threeFunc() ->()
  6. }
  7. class Yu: WUProtocol {
  8. func oneFunc() -> (Int) {
  9. return 88
  10. }
  11. func twoFunc() {
  12. }
  13. }
  14. //方法二:用extension
  15. protocol SomeProtocol {
  16. func requiredFunc()
  17. func optionalFunc()
  18. }
  19. extension SomeProtocol {
  20. func optionalFunc() {
  21. print("Dumb Implementation")
  22. }
  23. }
  24. class SomeClass: SomeProtocol {
  25. func requiredFunc() {
  26. print("Only need to implement the required")
  27. }
  28. }

访问控制

模块区分权限

  • open :允许其他模块访问,允许其他模块进行继承、重写(open只能用于类、类成员)
  • public : 允许其他模块访问,不允许继承、重写
  • internal :只允许当前模块中访问,不允许其他模块访问 (绝大部分实体都默认为 internal )
  • fileprivate :只允许当前实体的源文件中访问
  • private : 只允许在定义实体的封闭声明中访问

  • enum不能为case单独设置访问级别

image.png
image.png