Swift(十一、属性)


1、Swift入门学习笔记(第一版),对Swift的基础知识点进行梳理总结。知识点一直在变,只是作为参考,以苹果官方文档为准~

2、在学习完基本的知识点以后会结合官方文档及相关资料,在此版本的基础上进行添加更改。


十一、属性


1、存储属性

存储在特定类或结构体的实例里地一个变量或常量

struct Rectangle {
    var length:Int
    let width:Int
}
var rectangleA = Rectangle(length: 2, width: 18)
rectangleA.length = 3       //可修改,但是width不可修改

//let rectangleB = Rectangle(length: 19, width: 2)
//rectangleB.length = 2   //虽然结构体中length是变量属性,但是此处结构体的实例赋值给一个常量,则无法修改该实例的任何属性

原因:
结构体是值类型,值类型的实例被声明为常量时,其所有的属性也就变成了常量

区别于引用类型的类,把一个引用类型的实例赋给一个常量后,仍然可以修改该实例的变量属性


2、延迟存储属性

指当第一次被调用的时候才会计算其初始值的属性。


2.1、说明

lazy关键字声明,但是必须是变量,因为变量属性的初始值可以再实例构造完成之后才会得到。

常量不可以,因为常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。


2.2、使用场景

a、属性的值依赖于在实例构造过程后才会知道具体值

b、获得属性的初始值需要复杂或大量计算时


2.3、注意点

标记为lazy属性在没有初始化时就同时被多个线程访问,则无法保证该属性只会被初始化一次


3、计算属性

不直接存储值,提供一个getter和一个可选的setter,来间接获取和设置其他属性或变量的值

必须使用var关键字定义计算属性,包括只读计算属性,因为他们的值不是固定的


3.1、实例:一矩形长度固定,宽可变
struct Rectangle {
    let length:Double = 10.0
    var width :Double
    var square:Double {
        get {
            return length * width
        }
        set(newSquare) {
            width = newSquare/length
        }
        //便捷的setter声明,没有定义新值得参数名,使用默认名称newValue
//        set {
//            width = newValue/length
//        }
    }
}
var rectangle = Rectangle(width: 2.0)
print("rectangle Square:\(rectangle.square),length:\(rectangle.length),width:\(rectangle.width)")
rectangle.square = 100.0
//设置属性square会调用square的setter方法来修改width属性
print("rectangle Square:\(rectangle.square),length:\(rectangle.length),width:\(rectangle.width)")

Output:

rectangle Square:20.0,length:10.0,width:2.0
rectangle Square:100.0,length:10.0,width:10.0

3.2、便捷setter声明

与上面同,只是如果setter没有定义新值得参数名,那么可以使用默认名称newValue

在前面的代码中的setter备注部分


3.3、只读计算属性

只有getter没有setter的计算属性为计算属性,虽然只读但是仍要用var关键字,因为值不固定

get关键字和setter部分全部去除


4、属性观察器

a、监控和相应属性值的变化,属性被设置都会调用,包括新值和旧值相同的情况

b、可以为延迟属性外的其他存储属性添加属性观察器,也可以通过重写属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。(不需要为非重写的计算属性添加属性观察器,其可通过setter方法直接监控和响应变化)

c、为属性添加如下一个或全部观察器
willSet:新值被设置之前调用,指定新的常量名称传入新的属性值,不指定默认
didSet:被设置之后立即调用,指定新的参数名称传入旧的属性值,不指定默认oldValue

d、父类属性在子类的构造器中被赋值时,父类中的willSetdidSet观察器会被调用

e、如果在一个属性的didSet观察器里为它赋值,这个值会替换之前的值

class Figure {
    var weight:Double = 0.0{
        willSet(newWeight) {
            print("Weight:\(newWeight)")
        }
        didSet {
            if weight > oldValue {
                print("Amazing!You are fatter!")
            }else if weight == oldValue {
                print("Oh~There is nothing chang.")
            }else {
                weight = 0
                print("So sad!You get thinner!T^T")
            }
        }
    }
}
let myFigure = Figure()
myFigure.weight = 55.0

myFigure.weight = 60.2

myFigure.weight = 58.8

print(myFigure.weight)      //结果是0,因为变瘦后,我属性里设置值为0(验证点e)

Output:

Weight:55.0
Amazing!You are fatter!
Weight:60.2
Amazing!You are fatter!
Weight:58.8
So sad!You get thinner!T^T
0.0

5、全局变量和局部变量

a、全局变量和局部变量可以使用计算属性和属性观察器

b、全局变量或常量都是延迟计算的,跟延迟存储属性相似,不同的是全局变量或常量不需要标记lazy特性

c、局部范围的常量或变量不会延迟计算


6、类型属性

类型属性是类型本身特有,不管有多少实例,这些属性都只有唯一一份。用于定义特定类型所有实例共享的数据

必须指定默认值,延迟初始化


6.1、语法

类型属性作为类型定义的一部分写在类型最外层的花括号内,其作用范围在类型支持的范围内
使用static定义类型属性。在为类定义计算类型属性时,可以使用关键字class来支持子类对父类的实现

struct TestStruct {
    static var string = "structString"
    static var value:Int {
        return 1
    }
}

enum TestEnum {
    static var string = "enumString"
    static var value:Int {
        return 2
    }
}

class TestClass {
    static var string = "classString"
    static var value:Int {
        return 3
    }
}

//2、获取和设置属性
print(TestStruct.string)
TestStruct.string = "structStringChanged"

print(TestStruct.string)

print(TestEnum.value)

print(TestClass.value)

Output:

structString
structStringChanged
2
3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值