引言
最近学习Swift,初看很简单。深入下来发现,其实里面有稍显复杂的细节需要记住。希望通过此文总结Swift中属性、属性重写、常量变量等特性在Swift继承机制中的要点,帮助自己记住,也帮助需要的朋友对知识点的记忆和理解不再混乱。
摘要
对于初学者而言,本文着重围绕Swift属性,从4个方面分析总结Swift属性的各种使用方法,以及属性、属性观察器、setter、getter在继承中的重写规则
发车
一、属性的不同特性的组合
这里的特性一词指和属性相关的具有对立特性的4组性质,如下:
1.层级性,对象层级和类层级。
2.功能性,存储和计算。
3.加载方式,有延迟加载和非延迟加载。
4.附加操作,有set、get方法和willSet 、didSet观察器。
(以上所列举的知识点在Swift4.0 教程里有详细的讲解,本文只对细节方面的东西作出总结。)
若对以上4点进行排列组合,理论上将得到足足16种确切类型的属性,对于新手来说,这将会很混乱。这也是我写本文的初衷。当然,实际上,并没有这么多啦,有些组合是天生不支持的。只是在初学过程中,我们对于Swift支持哪种和哪种搭配一开始是混乱的,接下来我们来理清这些东西。
(一)、对象属性
只有可变对象存储属性可以使用lazy
只有可变存储型且非延迟属性可使用willSet和didSet属性观察器
set和get是计算属性的专利,不需要考虑存储属性
// 变存储属性
var objProperty1:String = ""
let objProperty2:String = ""
// 变存储属性 + 观察器
var objProperty3:String = ""{
// 属性观察器并不是必须的!
willSet{/* 操作newValue */}
didSet{/* 操作oldValue */}
}
// 计算属性,只能用var
var calProperty:Int{
set{/* 操作newValue */}
get{/* 返回计算的值 */}
}
(二)、类属性
由static和class修饰,我们用排除的思路来依依分析,首先,对于类属性,由于类没有自己的(显式)构造器,任何一个类属性(无论贫穷还是富贵,呸...无论是计算型还是存储型),因为没有构造器,所以必须在定义的时候设置默认值(可选类型除外)。因此,我们可以总结为static或class和lazy永远不可能放一起
static和class区别:
1、存储型类属性只能用static修饰,且不能被重写
2、计算型类属性可以用static也可以用class,只有class修饰的可以被子类重写
// 变存储属性
static var objProperty1:String = ""
// 常存储属性
static let objProperty1:String = ""
// 变存储属性 + 观察器
static var objProperty3:String = ""{
// 属性观察器并不是必须的!
willSet{/* 操作newValue */}
didSet{/* 操作oldValue */}
}
// 计算属性,只能用var, static修饰不能被重写
static var calProperty1:Int{
set{/* 操作newValue */}
get{/* 返回计算的值 */}
}
// 计算属性,class修饰能被重写
class var calProperty2:Int{
set{/* 操作newValue */}
get{/* 返回计算的值 */}
}
二、关于重写
(一)、类属性
类属性有且只有"class+var+变量名+计算属性"一种情况可以被重写
(二)、对象属性
1、凡是let常量属性均不可重写
2、可变存储属性和计算属性都只可以重写为计算属性
(三)、你以为这么简单就总结完了?
// 1、
class var classProperty3:String{ // 父
get{
return "classProperty3父类get的返回值"
}
set{
print("classProperty4 父类 set newValue:\(newValue)")
}
}
override class var classProperty3:String{ // 子
get{
return "classProperty3 子类 get"
}
set{
print("classProperty3 子类 set newValue:\(newValue)")
}
}
// 运行子类对象.classProperty3 = "newValue"
// 输出: classProperty3 子类 set newValue:newValue
// 2、
class var classProperty4:String{ // 父
set{
print("classProperty4 父类 set newValue:\(newValue)")
}
get{
return "classProperty4父类get的返回值"
}
}
override class var classProperty4:String{ // 子
willSet{
print("classProperty4 子类 willSet newValue:\(newValue)")
}
didSet{
print("classProperty4 子类 didSet oldValue:\(oldValue)")
}
}
// 运行:子类对象.classProperty4 = "newValue"
// 输出:
// classProperty4 子类 willSet newValue:newValue
// classProperty4 父类 set newValue:newValue
// classProperty4 子类 didSet oldValue: classProperty4父类get的返回值
// didSet后的oldValue是调取的父类的get方法
// 3、
var objp2:String = "varObjp2" // 父
override var objp2: String{ // 子
get{
return "子类objp2 get"
}
set{
print("子类objp2 set newValue:\(newValue)")
}
}
// 运行:子类对象.objp2 = "newValue"
// 输出:子类objp2 set newValue:newValue
// 4、
var objp31:String = "oldV31"{ // 父
willSet{
print("objp31 父类 WillSet newValue:\(newValue)")
}
didSet{
print("objp31 父类 DidSet oldValue:\(oldValue)")
}
}
override var objp31: String{ // 子
set{
print("objp31 子类 set newValue:\(newValue)")
}
get{
return "objp31 子类 get"
}
}
// 运行:子类对象.objp31 = "newValue"
// 输出:objp31 子类 set newValue:newValue
// 并不会调用父类的观察器
// 5、
var objp32:String = "oldV32"{ //父
willSet{
print("objp32 父类 WillSet newValue:\(newValue)")
}
didSet{
print("objp32 父类 DidSet oldValue:\(oldValue)")
}
}
override var objp32: String{ //子
willSet{
print("objp32 子类 willSet newValue:\(newValue)")
}
didSet{
print("objp32 子类 didSet oldValue:\(oldValue)")
}
}
// 运行:子类对象. objp32 = "newValue"
// 输出:
// objp32 子类 willSet newValue: newValue:newValue
// objp32 父类 WillSet newValue:newValue
// objp32 父类 DidSet oldValue:oldV32
// objp32 子类 DidSet oldValue:oldV32
// 6、
var objp41:String{
set{
print("objp41 父类 set newValue:\(newValue)")
}
get{
return "objp41父类get的返回值"
}
}
override var objp41: String{
willSet{
print("objp41 子类 willSet newValue:\(newValue)")
}
didSet{
print("objp41 子类 didSet oldValue:\(oldValue)")
}
}
// 运行:子类对象.objp41 = "newValue"
// 输出:
// objp32 子类 willSet newValue: newValue:newValue
// objp41 父类 set newValue:newValue
// objp32 子类 DidSet oldValue:objp41父类get的返回值
// 7、
var objp42:String{ //父
set{
print("objp42 父类 set newValue:\(newValue)")
}
get{
return "objp42父类get的返回值"
}
}
override var objp42: String{ //子
set{
print("objp42 子类 set newValue:\(newValue)")
}
get{
return "objp42 子类 get"
}
}
// 运行:子类对象.objp42 = "newValue"
// 输出:objp42 子类 set newValue:newValue
(四)、有一开始就对这7种重写方式不晕头的吗?反正我是晕了
通过做这七组对照试验,也算是终于把属性在Swift继承中的规则搞清楚了,折腾了好久(写上面的例子以及试验完又写这篇文章)也是真的挺伤神的,毕竟每个字句都是自己敲下来的纯手打。不过在写这一段话时,我也还是觉得值得的,通过这样一折腾,更好的掌握了Swift属性在继承特性中的机制,比起昨晚一开始看见就晕头的状态,现在也对这一部分的要点有了把握和信心~
结语
各位老铁如果发现文中的不足或错误,欢迎在评论中指出。望海涵~
另外,本文是原创文章,转载请附上原文地址,谢谢大家。
网友评论