属性的set get willSet didSet -!可空属性

属性的set get willSet didSet -!可空属性,第1张

概述简要说明 名称 功能 set 计算属性的赋值方法,设置属性的时候调用 get 计算属性的读取方法,取属性值得时候调用 willSet(newValue) 监视属性的方法,在属性值将要改变的时候调用,参数附带即将改变的值 didSet(oldValue) 监视属性的方法,在属性值改变后调用,参数附带改变之前的值 ? 和 ! 属性的可空标识符. ?表示可空, !表示强制拆包 set和get 在OC中属 简要说明
名称 功能
set 计算属性的赋值方法,设置属性的时候调用
get 计算属性的读取方法,取属性值得时候调用
willSet(newValue) 监视属性的方法,在属性值将要改变的时候调用,参数附带即将改变的值
dIDSet(oldValue) 监视属性的方法,在属性值改变后调用,参数附带改变之前的值
? 和 ! 属性的可空标识符. ?表示可空,!表示强制拆包
set和get

在OC中属性是由set和get方法来实现的,也就是说在打点调用属性的时候实际上是对属性的set和get方法进行调用,通过setget方法来实现对类中一个全局变量的读写,即时没有写set和get方法这两个方法也是隐式存在的.下面是OC中属性的实现原型

//普通方式声明属性@property(nonatomic,copy)Nsstring * str;//------------------------------------xx.h//内部原理{    Nsstring * str;}- (voID)setobject:(Nsstring *)anStr;- (Nsstring *)getStr;xx.M{    Nsstring * _object;}- (voID)setobject:(Nsstring *)anObject{    _object = anObject;}- (Nsstring *)getobject{    return _object;}

看的出来,OC中得属性实际上是对类内部的一个全局变量的 *** 作.我们可以通过重写set和get方法来实现属性变化的监听,属性的隐式修改等等.

而在swift中set和get方法并不是必须得.申明属性是直接生成一个存储属性,并不存在隐式的set和get方法,能够使用set和get方法的只有计算属性.计算属性本身并非一个值,只是一个能够通过打点调用set和get方法的假属性,计算属性并不能储存任何数据且必须实现get方法

class Object: NSObject {    //声明一个计算属性    var age:Int{        get{            print("get");        }        set(newValue){            print("\(newValue)")        }    }}//下面对这个属性进行使用let man = People();man.age = 10;print("\(man.age)")

输出结果:

set:10  //设置age的值 触发set方法并将值传递给set方法的参数newValueget     //输出age的值触发了get方法0       //输出age的值为0

可以看出 首先调用set方法 传递设置的值,newValue就是传递进来的值,设置完成后接着输出man.age属性,触发了get方法的调用,最后输出age的值,输出结果为0,也就是说并没有将设置的值保存起来.再来观察一下OC的属性原理,是不是和这个有点类似,如果在swift中创建一个私有的全局变量来储存set的值,读取的时候再返回这样就不就和OC中一样了吗?

private var newAge = 0;    var age:Int{        get{            print("get")            return newAge        }        set(newValue){            newAge = newValue;            print("set:\(newValue)")        }    }

输出结果:

set:10get10

好了 这样就还原了OC中的属性格式,在这两个方法中我们可以对属性的值进行处理,由于swift中默认属性没有set和get方法 所以我们无法重写父类属性的set和get方法.

willSet和dIDSet

这两个方法属于属性观察者.分别在属性值将要被设置和被设置以后调用.属于基本属性的方法,可以重写父类属性的这两个方法实现原有OC中重写set方法的功能.区别是初始化属性值的时候不会调用这两个方法.原理更加类似于通知,所以被成为属性观察者.

//创建一个观察者属性    var  name:String = "0"{        willSet(new){            print("will:\(new)");        }        dIDSet(old){            print("dID:\(old)");        }    }    //调用    var man = People()    man.name = "sad";    print("\(man.name)");    //输出结果

输出结果::

will:sad //将要设置值得时候调用,传递将要设置的值dID:0    //设置完毕,传递一个设置之前的值sad      //最终的值

测试结果显示,在第一次属性初始化为0的时候,观察者方法并没有调用,只有外部使用改变name值的时候才调用了观察者方法.

?和!

可空属性

在swift中所有的属性变量默认都不能为空,如果不可避免的可能造成为空属性.则需要声明为可空属性.

var name:string = "王五花"  //非空属性,此属性不可接受空值var name:string?            //可空属性,此属性可以接受空值 我们主要介绍这种

swift中空属性和OC中的空属性不同,虽然可以直接使用name == nilname != nil来判断,但是不可直接使用里面的值进行赋值 *** 作.这里就要说一下这个箱子概念了,当一个属性为可空的时候,这个属性被放到一个箱子中,这个箱子只有空和非空两种状态,由于属性是在箱子中的所以我们无法直接使用这个属性值,需要对箱子进行拆解 *** 作man.name = name!如果不拆箱,这个属性的类型是箱子的类型.

let man:People = People()//初始化没有对name进行赋值if man.name == nil {    print("空")}//对属性进行赋值man.name = "wang";print("没有进行拆包的值:\(man.name)")//没有使用"!"号进行拆包 *** 作if man.name != nil {    print("拆包以后的值:\(man.name!)")//使用了"!"拆包}//使用属性进行赋值let str:String = man.name!;//也可以不拆包使用Optional接受,Optional是一个枚举变量let op:Optional = man.name;print("\(op)")print("str会在接受值的时候强制拆箱 *** 作:\(str)")

输出结果:

空没有进行拆包的值:Optional("wang")拆包以后的值:wangOptional("wang")str会在接受值的时候强制拆箱 *** 作:wang

也就是说,当我们声明一个可空属性的时候var name:string?,这个属性被一个叫做Optional的箱子装了起来,这个箱子是允许为空的,使用man.name == nil语句来判断这个箱子里面有没有值,如果没有返回空,如果有则不为空.使用man.name = "wang";来向箱子中存放一个值,这个值必须和声明时的类型相同,当我们需要使用箱子的值的时候如果直接使用那么得到的是Optional值,并非是箱子中的值,所以要想使用箱子中的值需要使用!将箱子打开man.name!使用之前最好判断下

还有一种状态,就是在可空属性下面还有属性的时候

class People: NSObject {    var name:name? //People类的属性name是个可空的类型}class name: NSObject {    var English:String?//name类中English也是可空的    var Chinese:String = ""//Chinese属性是不可为空的 它有一个默认值.虽然看起来和没有一样}

这时使用name属性就要格外当心了.虽然系统会提示.

overrIDe func vIEwDIDLoad() {        super.vIEwDIDLoad()        let man:People = People()        man.name?.Chinese = "王"//name属性此时没有值,在这里的`?`表示尝试调用name属性 如果不为空则调用name后面的属性或方法        print("\(man.name?.Chinese)");//输出看看上面的赋值 *** 作会不会成功 结果为:nil 因为name并没有值,则不会执行`?`后面的语句 输出的nil是name的值        man.name = name()//对name进行初始化        man.name?.Chinese = "王五花"//再次进行尝试赋值        print("\(man.name?.English)")//打印English属性,此时English没有值 对name进行尝试解包,如果name不为空则使用后面的属性 结果为:nil 此时打开name输出的是English的值        print("\(man.name!.Chinese)")//打印有值得Chinese属性,这里使用'!'强制解包,因为我们知道anme已经初始化了.绝对不为空 结果为:王五花 此时强制打开name输出Chinese的值        man.name?.English = "WangWuhua" //尝试对English进行赋值 这里也可以用'!'强制解包        print("\(man.name?.English)")   //尝试调用name不解包English 结果为:Optional("WangWuhua") 这是我们输出的是English的值,因为没有解包 *** 作所以还是Optional类型        print("\(man.name?.English!)")  //尝试调用name 强制解包English 结果为:Optional("WangWuhua")此时我们强制解包English 满以为会输出WangWuhua,但结果并不是我们想象的那样,所以推断'?'并不具备解包能力,只是用来推断name属性是否为空,由此决定是否调用name下得属性        print("\(man.name!.English)")   //强制解包name 不解包English 结果为:Optional("WangWuhua") 这个比较好理解了.没有对English解包 *** 作        print("\(man.name!.English!)")  //强制解包name 强制解包English 结果为:WangWuhua 终于得到想要的结果了.必须要对所有属性进行强制解包才可以拿到最终值,就好像是一套套娃.我们必须将每个娃娃都打开才能看到最里面的东西    }
总结 set和get方法在Swift中没有默认创建,在基本属性中并不存在,所以无法重写父类的非计算属性的set和get方法.主要作用于对属性值在写入和读取过程中进行计算 *** 作 willSet和dIDSet类似于OC中得KVO,用于监视属性值的变化 可空属性,使用 var 属性名:类名? 这种方式可以声明一个可空属性,这里 ? 表示可空.这样系统将属性放到一个箱子中,通过对箱子是否为空的判断来确定是否有值,如果想要使用箱子中得值必须使用 ! 来强制打开箱子.如果属性下面还有属性需要使用 对象.属性?.属性A 来对属性进行一次是否为空得判断,如果为空则不调用属性A,如果确定有值可以使用 对象.属性!.属性A 来得到属性A的值 如果属性A也是可空类型 则需要 对象.属性!.属性A! 将每层的箱子都打开才能得到属性A的值 总结

以上是内存溢出为你收集整理的属性的set get willSet didSet -!可空属性全部内容,希望文章能够帮你解决属性的set get willSet didSet -!可空属性所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1077307.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存