美文网首页
Swift中的属性

Swift中的属性

作者: Sweet丶 | 来源:发表于2022-06-20 09:39 被阅读0次

另外几个知识点: 熟练使用Swift中的区间Swift枚举

本文的目的是做成一个手册,方便自己随时查看。

Swift属性.jpeg
一、存储属性
/* 1. 存储属性
  (0) 可以在类、结构体中使用,且初始化器调用完,所有成员必须有值。
 (1)不能写set、get方法;写了会变成计算属性
 (2)let和var的区别:let是第一次赋值之后不可变 
 */
class ZLPropertyClass {
    // 1.带初始值的存储属性
    var name: String = "dd"
    // 2.如果是可选类型,初始值是nil
    var age: Int?
    // 3.存储属性没有初始化值,且在初始化器中没有赋值,会报错
//    var isMan: Bool
    // 4.let类型的存储属性也是需要有初始值或者初始化器中赋值
    let author2: String
    // 5.let类型的存储属性内存也是在实例中的
    let author = "dandy"
    // 6. 设置闭包返回值为初始值时,闭包会在初始化器调用前调用
    // let类型设置闭包返回值为初始值的
    let testA: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        return formatter
    }()
    
    // var类型设置闭包返回值为初始值
    var testB: DateFormatter = { DateFormatter() }()
    
    // 初始化器,初始化器调用完,所有成员必须有值(或者是lazy、可选类型)
    init() {
        // 上面的author2没有初始值,在这里赋值也是一样的
        author2 = "dandy2"
    }
}
二、类型存储属性
/* 类型存储属性:
   1.在类、结构体、枚举中可以定义,使用static修饰,不能用class修饰。
   2.static修饰的变量默认是lazy类型的,必须要有初始值(初始值可以是闭包的返回值)。
   3.类型存储属性本质是全局变量。
 */
class ZLTypePropertyClass {
    // 使用static声明为类型存储属性
    static var langugue: String = "Swift"
    static let company: String = "Apply"
    
    // 类型存储属性无论是let还是var类型都必须有初始值,不然会报错,而且在初始化器设置也没用的
//    static var aa: Bool
//    static let bb: Bool
    
    // 不允许使用class来修饰存储属性
//    class let cc = false
//    class var dd = true
}
三、计算属性
/* 计算属性:
   1.在类、结构体、枚举中可以定义, 只能用var修饰,本质上是一个方法。
   2.可以有set、get方法,至少要有get方法。
   3.子类可重写父类存储、计算属性为计算属性,不可重写为存储属性。
 */
class ZLComputePropertyClass: ZLPropertyClass {
    var carName = "比亚迪·唐 C15"
    // 1.有set和get方法的计算属性
    var displayName1: String {
        set { carName = newValue }
        
        get { return "电汽车" }
    }
    
    // 2.只有get方法时可以不写set和get关键字
    var displayName2: String {
        if carName.contains(substring: "比亚迪·唐") {
            return "比亚迪·唐"
        }
        return "其它"
    }
     
    // 3. 如果get方法中只有一行代码,那么可以省略return
    var displayName3: String { "汽车" }
    
    // 4. 子类只能重写var类型的存储属性, 且只能重写为计算属性,且必须有set和get两个方法
    override var name: String {
        set {}
        get { "" }
    }
}
四、类型计算属性
/* 类型计算属性:
   1.在类、结构体、枚举中可以定义,用static修饰, 在类中也可使用class修饰。
   2.在类中使用class修饰的计算属性,子类可重写为类型计算属性.
 */
class ZLTypeComputePropertyClass {
    static var name = "比亚迪·唐 C15"
    
    // 1.static修饰,有set和get方法的计算属性
    static var displayName1: String {
        set {  name = newValue }
        
        get { return "电汽车"  }
    }
    
    // 2.class修饰,只有get方法时可以不写set和get关键字
    class var displayName2: String {
        if name.contains(substring: "比亚迪·唐") {
            return "比亚迪·唐"
        }
        return "其它"
    }
    
    // 3. class修饰,如果get方法中只有一行代码,那么可以省略return
    class var displayName3: String { "汽车" }
    
    // 4. class修饰,有set和get方法的计算属性
    class var displayNam4: String {
        set { name = newValue }
        
        get { "出租车" }
    }
}

/* 子类重写父类的类型计算属性时,可读可写的权限不少于父类
 */
class ZLSubClass: ZLTypeComputePropertyClass {
    // 1.重写父类的类型计算属性,也用class修饰,那么自己类的子类也可重写计算属性
    override class var displayName3: String { "电动汽车" }
    
    // 2.重写父类的类型计算属性,也可以用static修饰,但自己的子类不能再重写
//    override static var displayName3: String { "电动汽车" }
    
    // 3. 重写父类的类型计算属性,父类计算属性是get,那么可以有set和get,也可以只有get
//    override class var displayName2: String { "特斯拉" }
    override class var displayName2: String {
        set {}
        get { "特斯拉" }
    }
    
    // 4.重写父类的类型计算属性,父类计算属性是set + get, 子类必须也有set、get
    override class var displayNam4: String {
        set {}
        get { "高级出租车" }
    }
}
五、属性观察器
/* 属性观察器指的是willSet、didSet方法,可以通过他们来监听存储属性变化.
  1.只可以对var类型添加属性观察器,并且计算属性\类型计算属性不能添加属性监听器.
  2.添加属性观察器之后,对于存储属性,初始值及初始化器中的赋值都不会触发观察器;
    对于类型存储属性来说,除初始值外的变化都会触发观察器。
  3.willset的默认参数newvalue,didset的默认oldvalue.
  4.本质上是在修改值之前和之后调用对应的willset\didset方法.
 */
class ZLPropertyListen {
    /// 0. 计算属性看子类重写时设置属性监听器
    var computeP: Int {
        set { print("computeP.set") }
        
        get {
            print("computeP.get")
            return 5
        }
    }
    
    // 1.存储属性带初始值的观察:在初始化器调用完成后的值变化才会触发
    var status = 0 {
        willSet { print("status.willSet", newValue) }
        
        didSet { print("status.didSet", oldValue) }
    }
    
    // 2.可选类型的观察:同1
    var name: String? {
        willSet { print("name.willSet",newValue) }
        
        didSet { print("name.didSet",oldValue) }
    }
    
    // 3.带闭包返回值为初始值的属性观察器:同1
    var dispalyName: String = { "红旗" }() {
        willSet { print("dispalyName.willSet", newValue) }
        
        didSet { print("dispalyName.didSet", oldValue) }
    }
    
    // 4.static类型存储属性设置观察器(class不能用来修饰存储属性):除初始值外的变化会触发
    static var staticP = { DateFormatter() }() {
        willSet { print("staticP.willSet", newValue) }
        didSet { print("staticP.didSet", oldValue) }
    }
    
    // 这里面只有类型存储属性staticP的赋值会触发属性观察器
    init() {
        status = 999
        name = "dandy"
        dispalyName = "国产汽车"
        Self.staticP = DateFormatter()
    }
}

/* 子类重写父类的存储属性
  1.如果重写为计算属性,那么不能再添加观察器
  2.如果重写时添加观察器,那么不能再写set、get(即不能重写为计算属性)
  3.子类重写父类的计算属性或类型计算属性时,可以不重写为计算属性,只添加属性观察器.
  4.子类重写父类属性为计算属性时,不会触发父类的属性观察器.
  5.子类初始化器中super.init()之后的赋值会触发子类和父类的属性观察器,调用顺序:
    ①重写时添加属性观察器:子类willSet->父类willSet->父类didSet->子类didSet
    ②重写父类计算属性时添加属性观察器:父类get->子类willSet->父类set->子类didSet
    ③子类初始化器中使用super.property来修改属性值时,只会触发父类的计算属性方法或父类属性监听器
 */
class ZLSubPropertyListen: ZLPropertyListen {
    // 1.重写时设置监听器,不能再写set、get
    override var status: Int {
        willSet { print("子类status.willSet", newValue) }
        didSet { print("子类status.didSet", oldValue) }
    }
    
    // 2.重写为计算属性,不能再设置监听器
    override var name: String? {
        set { print("子类name.set", newValue) }
        get {
            print("子类name.get", name)
            return "流浪地球🌏"
        }
    }
    
    // 3.重写父类的计算属性,但只添加属性观察器
    override var computeP: Int {
        willSet { print("子类computeP.willSet", newValue) }
        didSet { print("子类computeP.didSet", oldValue) }
    }
    
    // 自身属性
    var SubP = 100
    
    // 子类初始化器中给父类属性赋值必须在super.init()之后,之前只能给自身类中属性赋值
    // 在super.init()之后给父类的属性赋值会触发子类重写时添加的属性监听器然后触发父类的属性监听器
    // 在super.init()之后如果用super.property来进行赋值,只会触发父类的计算属性方法或父类属性监听器
    override init() {
        SubP = 80
        super.init()

        status = 999
        name = "dandy"
        dispalyName = "国产汽车"
        computeP = 666
        
        super.status = 999
        super.name = "dandy"
        super.dispalyName = "国产汽车"
        super.computeP = 666
    }
}
六、Lazy属性
/* lazy属性
   1.lazy可用来修饰var存储属性,类型存储属性let、var默认是lazy;不能用来修饰计算属性
   2.本质上是在变量初始化时先将变量初始化为一个标识,后续真正使用时才初始化
   3.类型存储属性默认就是lazy的,但也可以使用let修饰
   4.多线程使用时需要注意,lazy并不保证线程安全
   5.lazy属性初始值生成不会触发属性监听器
 */
class ZLLazyProperty {
    // lazy属性是可选类型时,默认值可以是nil
    lazy var aaa: Int? = nil
    
    // 用lazy修饰之后,会先初始化为一个lazy标记,在实际用到时才会生成DateFormatter
    lazy var dateFormatter = DateFormatter()
    
    // 使用lazy修饰,闭包会在真实用到titleLabel时才调用
    lazy var titleLabel: UILabel = {
        print("titleLabel初始化值闭包调用---")
        return UILabel()
    }()
    
    // 使用static修饰的类型存储属性,默认就是lazy,不需要用lazy修饰.
    static let shared = ZLLazyProperty()
    
    // 使用static修饰的类型存储属性,闭包会在实际用到时调用
    static var shared2: ZLLazyProperty = {
        print("shared2初始化值闭包调用---")
        let shared2 = ZLLazyProperty()
        // some init setting
        return shared2
    }()
}
七、全局变量、局部变量
/* 全局变量
  1.不需要用static修饰, 必须要有初始值,默认是lazy的,不能用lazy修饰。
  2.可以是计算属性或添加属性观察器,但不能与计算属性同时存在。
 */
var productName = "productName" {
    willSet {}
    didSet {}
}
let productName2 = "productName2"
var productName3: String {
    set {}
    get { "productName3" }
}

func testVar() {
    /* 局部变量可以用lazy修饰,其余与全局变量一样 */
    lazy var product = "product" {
        willSet {}
        didSet {}
    }
    let product2: String
    var product3: String {
        set {}
        get { "product3" }
    }
    
    product2 = "product2"
    print(product, product2, product3)
}

相关文章

  • OC的@property与Swift的存储属性/计算属性类比

    Swift中的计算属性/存储属性与OC中的@property   Swift中引入了存储属性、计算属性的概念,存储...

  • Swift 属性

    Swift 属性 在Swift中属性主要分为存储属性、计算属性、延迟存储属性、类型属性这四种,并且Swift还提供...

  • Swift进阶(三)--- 属性

    Swift的属性 在swift中,属性主要分为以下几种: 存储属性 计算属性 延迟存储属性 类型属性 一:存储属性...

  • 浅谈 Swift 中的属性(Property)

    Properties in Swift 前言 Swift 中的属性分为存储属性与计算属性,存储属性即为我们平时常用...

  • 第10章:属性

      在Swift中枚举、结构体、类都可以有属性,属性描述了类型的某个特性。在Swift中属性从大的方面分可以分为存...

  • Swift学习-进阶02

    swift对象本质,一个swift的对象默认占用16字节大小,在内存中的结构: swift类结构: 属性 存储属性...

  • Swift 计算属性、存储属性

    属性 Swift中的属性分为存储属性(sorted variable)和计算型属性(computed variab...

  • Swift中的属性

    1. 存储属性 简单来说,每一个存储属性就是存储在特定类或结构体实例里的一个常量或变量。存储属性可以使变量存储属性...

  • Swift中的属性

      我们都知道,类是由属性和方法组成的,一般而言,属性主要是用来访问数据成员,而方法则是用来执行某些操作,比如说计...

  • swift中的属性

    属性可以将值与特定的类、结构体或者是枚举联系起来。 一、简介 存储属性与计算属性的差异: 存储属性会存储敞亮或者变...

网友评论

      本文标题:Swift中的属性

      本文链接:https://www.haomeiwen.com/subject/jjwrvrtx.html