可以在类、结构体、协议中定义属性,属性可以是变量,也可以是常量。

1.在结构体中声明属性:

struct RectStore{
    var length : Int
    var breadth : Int
}
var r = RectStore(length:5,breadth:5)//length = 5
r.length = 6//length = 6

但因为结构体是值引用类型,所以当我们把结构体声明为常量时,是不可以改变结构体内部属性值的。如下:

let r1 = RectStore(length: 5, breadth: 5)
r1.length = 6 //报错:Cannot assign to property: 'r1' is a 'let' constant

2.懒加载

定义为懒加载的属性

struct Rect{
    
    var length : Int
    let breadth : Int
    
    init(length : Int, breadth: Int) {
        print("Rect struct is initialised now from the lazy var property")
        self.length = length
        self.breadth = breadth
    }
    
}

struct Square{
    
    var sidesEqual : Bool
    
    lazy var r = Rect(length: 6, breadth: 6)
    
    init(sidesEqual : Bool) {
        self.sidesEqual = sidesEqual
    }
}
var s = Square(sidesEqual: false)

if s.sidesEqual
{
    print(s.r.length)
}
else{
    print("Rect struct hasn't been initialised using the lazy var")  //this gets printed
}
//打印结果:Rect struct hasn't been initialised using the lazy var
var s1 = Square(sidesEqual: true)

if s1.sidesEqual
{
    print(s1.r.length)
}
else{
    print("Rect struct hasn't been initialised using the lazy var") //not printed
}
//打印结果:Rect struct is initialised now from the lazy var property   \n 6

从上面的例子可以看出,懒加载会在调用之前在初始化。

2.1懒加载定义闭包

class Name{
    var name : String?
    lazy var greet : String = {[weak self] in//为了防止循环引用,我们使用weak self
        guard let s = self else {
            return "Unable to unwrap self"
        }//防止循环引用
        guard let n = s.name else {
            return "No name found"
        }
        return "Hi, \(n)"
    }()
    init(name : String){
        self.name = name
    }
}
var n = Name(name: "Anupam")
print(n.greet)//打印结果:Hi, Anupam

此时,我们把name置空,看看效果


n.name = nil
print(n.greet)//打印结果:Hi, Anupam

发现打印结果没有改变,上述例子表明,懒加载只初始化一次;所以不论变量如何变化,闭包的结果是不变的.
再看个例子:

//在举个例子
var nn = Name(name : "Bobby")
nn.name = nil
print(nn.greet)//打印结果:No name found

nn.name = "Bobby"
print(nn.greet)//打印结果:No name found

声明属性,在属性内部实现get、set方法;实现属性的读写

struct Rectengle{
    var length : Double
    let breadth : Double
    var area : Double{
        get{//根据长框,算出面积;当外部直接调用area时,调用
            return length * breadth
        }
        set(newArea){//根据给定的面积、宽,计算出长;当外部给area赋值时调用
            length = newArea / breadth
        }
    }
}

var rs = Rectengle(length:6,breadth:5)
print(rs.area)//打印结果:30.0 调用的是get方法

rs.area = 40
print(r.length)//打印结果:8.0 调用的是set方法
//如果set方法中参数名不明确说明,Swift默认属性名为newValue,可以简化为下面方式
struct RectangleSimply{
    
    var length : Double
    let breadth : Double
    
    var area : Double {
        
        get{
            return length*breadth
        }
        set
        {
            length = newValue/breadth
        }
    }
}

但是需要注意的是:
1、将实现了get、set方法的属性,定义为lazy var;也不能定义为常量。
2、定义了set方法的属性,必须定义get,不然会报错。
3、定义了get方法的属性,可以不定义set方法,此时,属性只支持读,不支持写。

struct readOnlyRect{
    var length : Double
    var breadth : Double
    var area : Double{
        get{
            return length * breadth
        }
    }
    //周长
    var perimeter : Double{
        get{
            return length * 2 + breadth * 2
        }
    }
}
var rr = readOnlyRect(length:6,breadth:5)
print(rr.area)//打印结果:30
rr.area = 40 //报错,因为未实现,set方法;声明变量默认是包含get和set方法,只是读取的是变量本身的值。

3.属性观察者

对属性变化做出响应,包含两个方法:
(1)willSet:在值存储之前触发,它允许我们在值更改之前读取旧值。我们可以使用关键字newValue访问新值。
(2)didSet:在值存储之后触发,它允许我们读取新值和旧值。我们可以使用关键字oldValue访问旧值。
给属性set值时,会触发属性观察者。

struct yardToInchesConversion{
    var yard : Double = 0{
        willSet{
            print("new value of yard \(newValue)")
        }
        didSet{
            print("old value of yards \(oldValue)")
            inches = yard * 36
            print("Updated value of inches \(inches)")
        }
    }
    var inches : Double = 0
}

var yi = yardToInchesConversion()
yi.yard = 22
//打印结果:
//new value of yard 22.0
//old value of yards 0.0
//Updated value of inches 792.0

4.全局变量和静态变量

静态变量在子类中不能重写

class A {
    var testNumner : Int = 10
    static var i : Int = 5
    static var name : String{
        return "Hello World"
    }
    class var multiplyByANumber: Int {
        return i * 5
    }
    static func printI(){
        print("Value of i is \(i)")
    }
    class func appendClassName(){
        print("Class A Hello World")
    }
}

class SubClass : A{
    override class var multiplyByANumber : Int{
        return i * 5 * 5
    }
    override class func appendClassName(){
        print("Class SubClass Hello World")
    }
}

5.subscript

下标是访问集合、列表、序列元素的捷径,我们是用array[index]、dictionary[key]等,相应的,我们可以定义一个任意类型的下标。我们可以为同一类型定义多个下标,并根据传递给下标的索引值的类型选择要使用的适当下标重载。

class M {
private var month = ["Jan", "Feb", "March", "April"]
subscript(index: Int) -> String {
    get {
        return month[index]
    }
    set(newValue) {
        self.month[index] = newValue
    }
}
}
var m = M()
m[3] //April
m[0] = "Dec"
posted on 2021-07-06 13:41  蓬松小辉煌  阅读(150)  评论(0编辑  收藏  举报