Swift - 属性(Property)

2020-06-22  本文已影响0人  iVikings

属性(Property)

Swift 中跟实例相关的属性可以分为 2 大类

类似于成员变量这个概念
存储在实例的内存中
结构体、类 可以定义存储属性
枚举 不可以定义存储属性

本质就是方法(函数)
不占用实例的内存
枚举、结构体、类 都可以定义计算属性

struct Circle {
    // 存储属性
    var radius: Double
    // 计算属性
    var diameter: Double {
        set {
            radius = newValue / 2
        }
        get {
            radius * 2
        }
    }
}

var circle = Circle(radius: 8)
print(circle.radius, circle.diameter)
// 8.0, 16.0

存储属性

关于存储属性,Swift 有个明确的规定

可以在初始化器里为存储属性设置一个初始值
可以分配一个默认的属性值作为属性定义的一部分

计算属性

struct Circle {
    // 存储属性
    var radius: Double
    // 计算属性
    var diameter: Double {
        set(newDiameter) {
            radius = newDiameter / 2
        }
        get {
            radius * 2
        }
    }
}
struct Circle {
    // 存储属性
    var radius: Double
    // 计算属性
    var diameter: Double {
        get {
            radius * 2
        }
    }
}

struct Circle {
    // 存储属性
    var radius: Double
    // 计算属性
    var diameter: Double { radius * 2 }
}

let 代表常量:值是一成不变的
计算属性的值是可能发生变化的(即使是只读计算属性)

枚举 rawValue 原理

枚举原始值 rawValue 的本质是:只读计算属性

enum Directon: String {
    case north = "north", south = "south", east = "east", west = "west"
    var rawValue: String {
        switch self {
        case .north:
            return "north"
        case .south:
            return "south"
        case .east:
            return "east"
        case .west:
            return "west"
        }
    }
}

延迟存储属性(Lazy Stored Property)

class Car {
    init() {
        print("Car init!")
    }
    func run() -> Void {
        print("Car is running!")
    }
}

class Person {
    lazy var car = Car()
    init() {
        print("Person init!")
    }
    func goOut() -> Void {
        car.run()
    }
}

class PhotoView {
    lazy var image: String = {
       let url = ""
        return url
    }()
}

注意点

struct Point {
    var x = 0
    var y = 0
    lazy var z = 0
}
let p = Point()
print(p.z)
// error:Cannot use mutating getter on immutable value: 'p' is a 'let' constant

属性观察器(Property Observer)

struct Circle {
    // 存储属性
    var radius: Double {
        willSet {
            print("willSet", newValue)
        }
        didSet {
            print("didSet", oldValue, radius)
        }
    }
    init() {
        self.radius = 1.0
        print("Circle init!")
    }
}
  • willSet 会传递新值,默认叫 newValue
  • didSet 会传递旧值,默认叫 oldValue
  • 在初始化器中设置属性值不会触发 willSetdidSet
  • 在属性定义时设置初始值也不会触发 willSetdidSet

全局变量、局部变量

计算属性、属性观察器的功能,同样可以应用在全局变量、局部变量身上

var num: Int {
    get { return 10 }
    set { print("setNum", newValue) }
}

func getAge() -> Int {
    var age = 10 {
        willSet {
            print("willSet", newValue)
        }
        didSet {
            print("didSet", oldValue)
        }
    }
    age = 11
    return age
}

inout 的本质总结

struct Shape {
    var width: Int
    var side: Int {
        willSet { print("willSetSide", newValue) }
        didSet { print("didSetSide", oldValue, side) }
    }
    var girth: Int {
        set {
            width = newValue / side
            print("setGirth", newValue)
        }
        get {
            print("getGirth")
            return width * side
        }
    }
    func show() {
        print("width = \(width), side = \(side), girth = \(girth)")
    }
}

func test(_ num: inout Int) {
    num = 20
}

var s = Shape(width: 10, side: 4)
test(&s.width)
s.show()
print("------------")
test(&s.side)
s.show()
print("------------")
test(&s.girth)
s.show()


/**
getGirth
width = 20, side = 4, girth = 80
------------
willSetSide 20
didSetSide 4 20
getGirth
width = 20, side = 20, girth = 400
------------
getGirth
setGirth 20
getGirth
width = 1, side = 20, girth = 20
*/

类型属性(Type Property)

struct Car {
    static var count: Int = 0
    init() {
        Car.count += 1
    }
}

类型属性细节

上一篇下一篇

猜你喜欢

热点阅读