08-Swift属性(Properties)

属性:将值与特定的类、结构体或枚举关联;
存储属性:存储常量或变量作为实例的一部分;
计算属性:用于计算一个值(不是存储);
类型属性:属性可以直接作用于类型本身(存储属性和计算属性通常与特定类型的实例关联);
 计算属性可以用于类、结构体和枚举,存储属性只能用于类和结构体。


一、存储属性


 一个存储属性就是存储在特定类或结构体实例中一个常量或变量。存储属性可以是变量存储属性(用var关键字定义),也可以是常量存储属性(用let关键字定义)。

struct PersonStruct {
    var name:String
    let tel:Int
}
var liming = PersonStruct(name: "liming", tel: 10086);
// liming实例中包含了,name变量存储属性和tel常量存储属性
  • 常量结构体的存储属性,创建的一个结构体实例,赋值给常量,则无法修改该实例中的任何属性,即使结构体中定义的是变量存储属性:
// zhangsan声明为变量,即使name是变量属性,是无法再修改
let zhangsan = PersonStruct(name: "zhangsan", tel: 10000);
zhangsan.name = "张三";  // 这里是报错

注意:
结构体属于值类型,但值类型的实例声明为常量时,它的所有属性也就成为常量;
类属于引用类型,将一个引用类型的实例赋值给一个常量后,仍然可以修改实例中变量属性;

  • 延迟存储属性(懒加载),即属性第一次被调用的时候才会创建并加载到内存中。与OC不同,swift专门用lazy关键字来定义某个属性为懒加载:
【注: 如果不熟悉懒加载的,一定要自己实际操作一次,通过打印信息了解这个懒加载过程】
// 懒加载【单例模式: 懒汉式、饿汉式,懒加载其实是属于单例模式中的懒汉式】
class PersonClass {
    // 定义数据源属性,这个属性是属于懒加载,即在第一次使用的时候才会被调用
    lazy var dataArray : [String] = {
        // 此是dataArray初始化闭包
        () -> [String] in
        print("dataArray加载到内存中");
        return ["zhangsan", "lisi", "wangwu"]
    }()
    
    // 说hello的函数
    func speak(name:String) {
        print("hello, \(name)!");
    }
}
// 实例化PersonClassz
// 注意看打印信息,此时dataArray是没有实例化的!!!
let person = PersonClass();
// 打印出dataArray中的名字
print("遍历person实例中的dataArray");
// 当person.dataArray的时候才dataArray才会被加载,即是初始化的闭包才执行调用
for name in person.dataArray {
    person.speak(name);
}

懒加载格式:
lazy var 变量: 类型 = { 创建变量以及初始化相关代码 }()


二、计算属性


  • 除了存储属性外,类、结构体、枚举可以定义计算属性,计算属性不直接存储值,而是提供一个getter和一个可选setter,来间接获取和设置其他属性或变量的值:
// set和get是针对 计算变量(Calculated property) 不可以赋值的     
// 普通的存储变量(storage property)才是可以赋值的
class SpeakClass {
    // _name是存储变量(Calculated property),是可以进行赋值的
    var _name:String = "";
    // name是属于计算变量(storage property),不可以赋值的,即有别于OC的set/get方法
    var name:String {
        // 写法一,定义新值参数名newName
//        set(newName) {
//            print("set");
//            _name = newName;
//        }
        // 写法二,没有定义新值参数名,直接使用默认名称newValue
        set {
            print("set");
            // 使用默认名称newValue
            _name = newValue;
        }
        get {
            print("get");
            var str = _name;
            if str.isEmpty {  
                // 设置默认值
                str = "swift";
            }
            return str;
        }
    }
}
// 实例化操作
let speak = SpeakClass();
// 会调用到name的get方法
print("1-hello, \(speak.name)");
// 会调用到name的set方法
speak.name = "EndEvent";
// 会调用到name的get方法
print("2-hello, \(speak.name)");
输出效果:
get
1-hello, swift
set
get
2-hello, EndEvent


三、属性观察器


属性观察器监控和相应属性值的变化,每次属性被设置值的时候都会调用属性观察器,甚至新的值和现在的值相同的时一样会调用。
 除了延迟属性外,其他存储属性都可以添加属性观察器,可以通过重写属性的方式为继承属性(包括存储属性和计数属性)添加属性观察器。

注意: 不需要为非重写计算属性添加属性观察器,因为通过它的setter直接监控和响应值的变化。

可以为属性添加一个或全部观察器:
 - willSet在新的值被设置之前调用。willSet观察器会将新的属性值作为常量参数传入,在willSet的实现代码中可以为这个参数指定名称,如果不指定也可用,默认名称为nameValue
 - didSet在新的值被设置之后立即调用。didSet观察器会将旧的属性作为参数传入,可以为该参数命名或使用默认参数名oldValue;

class StepCount {
    // totalSteps是存储属性,包含有`willSet`和`didSet`观察器
    // 总步数,初始化0
    var totalSteps:Int = 0 {
        willSet {  // 在新的值被设置之前调用
            print("将要设置: \(newValue)");
        }
        didSet {  // 新的值被设置之后立即调用
            print("增加步数: \(totalSteps - oldValue)");
        }
    }
}
// 实例化
let step = StepCount();
step.totalSteps = 300;
step.totalSteps = 1000;

注意: 当totalSteps设置新值的时,它的willSetdidSet观察器都会被调用,甚至当新的值和现在的值完全一样也都会调用。


四、全局变量和局部变量


 计算属性和属性观察器说描述的模式可以是全局变量或局部变量。全部变量在函数、方法、闭包或任何类型之外定义的变量。局部变量是在函数、方法或闭包内部定义的变量。
 全局或局部范围都可以定义计算型变量和给储存罐型变量定义观察器。计算型变量与计算属性一样,返回一个计算的值而不是存储值,声明格式完全一个。

全局的变量和常量都是延迟计算的,与延迟存储属性相似。不同在于,全局的变量或常量不需要标记lazy关键字(即全局变量或常量都是属性懒加载)。
局部范围的常量或变量不会计算。


五、类型属性


类型属性用于定义特定类型所有实例共享的数据,比如所有实例都能访问的变量或常量(类似C语言中的静态变量或静态常量)。

跟实例的存储属性不同,必须给存储类型属性指定默认值,因为类型本身无法在初始化过程中使用构造器给类型属性赋值。
存储类型属性是延迟初始化,只有在第一次被访问的时候才会被初始化。即时被多条线程同时访问,系统也保证只会对其进行初始化一次,并且不需要用lazy关键字。

  • 类型属性语法。在C或OC中,与某个类型关联的静态常量和静态变量,是作为全局静态变量定义的。但在swift中,类型属性是作为类型定义的一部分写在类型最外层的花括号内,因此作用范围也是在类型支持的范围内。使用关键字来定义类型属性:
struct SomeStructure {
    // 使用关键字`static`定义类型属性
    static var storedTypeProperty = "Some value."
    // 类型属性
    static var computedTypeProperty: Int {
        return 1
    }
}
  • 获取和设置类型属性。与实例属性一样,类型属性的访问也是通过点语法来操作。但类型属性通过类本身来获取和设置,而不是通过类的实例:
struct SomeStructure {
    // 使用关键字`static`定义类型属性
    static var storedTypeProperty = "Some value."
    // 类型属性
    static var computedTypeProperty: Int {
        return 1
    }
}
// 注意是通过类型本身来获取和设置!!!
// 获取SomeStructure中的类型属性storedTypeProperty
print(SomeStructure.storedTypeProperty)
// 设置SomeStructure中的类型属性storedTypeProperty
SomeStructure.storedTypeProperty = "Another value."
// 获取SomeStructure中的类型属性storedTypeProperty
print(SomeStructure.storedTypeProperty)
// 获取SomeStructure中的类型属性computedTypeProperty
print(SomeStructure.computedTypeProperty);
输出结果:
Some value.
Another value.
1


注:xcode7.3环境

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容