swift基础-19-类的属性

类的基本定义
Swift中的结构体和类非常相似, 但是又有不同之处
类是具有相同属性和方法的抽象
格式:

class 类名称 {
    类的属性和方法
}
class Rect {
    var width:Double = 0.0
    var height:Double = 0.0
    func show() -> Void{
        print("width = \(width) height = \(height)")
    }
}
// 类没有逐一构造器
var r1 = Rect(width: 10.0, height: 10.0) // ERROR

类是引用类型, 对象之间的赋值其实是将r2指向了r1的存储空间, 所以他们是两个共享同一块存储空间, 修改其中一个会影响到另外一个

var r1 = Rect()
var r2 = r1
r1.width = 99
r2.width // 99
r2.width = 88
r1.width // 88

恒等运算符, 用于判断是否是同一个实例, 也就是是否指向同一块存储空间

=== !==
var r3 = Rect()
if r1 === r2
{
    print("指向同一块存储空间") // "指向同一块存储空间\n"
}
if r1 !== r3
{
    print("没有指向同一块存储空间") // "没有指向同一块存储空间\n"
}

存储属性
其实Swift中的存储属性就是以前学习OC中的普通属性, 在结构体或者类中定义的属性, 默认就是存储属性

struct Person {
    var name: String
    var age: Int
}
var p:Person = Person(name: "solozyx", age: 99)
p.name = "solo"
p.age = 99

常量存储属性
常量存储属性只能在定义时或构造时修改, 构造好一个对象之后不能对常量存储属性进行修改

struct Person2 {
    var name: String
    var age: Int
    let card: String // 身份证
}
var p2: Person2 = Person2(name: "solozyx", age: 99, card: "123456")
p2.name = "solo"
p2.age = 99
// 构造好对象之后不能修改常量存储属性
// p2.card = "56789" // 错误

结构体和类常量与存储属性的关系
结构体和枚举是值类型
类是引用类型

struct Person3 {
    var name: String
    var age: Int
}
let p3: Person3 = Person3(name: "solozyx", age: 99)
// 因为结构体是值类型, 所以不能修改结构体常量中的属性
// 不能修改结构体/枚举常量对象中的值, 因为他指向的对象是一个常量
// p3.name = "solo" // 错误
// 不能修改结构体常量对象的值
// p3 = Person(name: "solo", age: 9) // 错误
class Person4 {
    var name: String = "solo"
    var age: Int = 99
}
let p4:Person4 = Person4()
// 可以修改类常量中的值, 因为他指向的对象不是一个常量
p4.name = "solo"
// 不可以修改类常量的指向
//p4 = Person4()

延迟存储属性
Swift语言中所有的存储属性必须有初始值, 也就是当构造完一个对象后, 对象中所有的存储属性必须有初始值, 但是也有例外, 其中延迟存储属性可以将属性的初始化推迟到该属性第一次被调用的时候
懒加载应用场景:
1.有可能不会用到
2.依赖于其它值

class Line {
    var start:Double = 0.0
    var end: Double = 0.0
    // 如果不是lazy属性, 定义的时候对象还没有初始化, 所以不能访问self
    // 如果加上lazy, 代表使用时才会加载, 也就是使用到length属性时才会调用self,
    // 而访问一个类的属性必须通过对象方法, 所以访问时对象已经初始化完成了, 可以使用self
    lazy var length: Double = self.getLenght()
    // 通过闭包懒加载
    lazy var container: Array<AnyObject> = {
        print("懒加载")
        //return self.end - self.start
        var arrM = []
        return arrM as [AnyObject]
    }()
    func getLength() ->Double
    {
        print("懒加载")
        return end - start
    }
}

var line = Line() // Line
line.end = 150.0 // Line
print(line.getLength()) // "150.0\n"
print("创建对象完毕") // "创建对象完毕\n"
print(line.length) // "150.0\n"
var arrM = line.container // []
arrM.append("1")  // ["1"]
arrM.append(5) // ["1", 5]
print(arrM) // "[1, 5]\n"

计算属性
1.Swift中的计算属性不直接存储值, 跟存储属性不同, 没有任何的"后端存储与之对应"
2.计算属性用于计算, 可以实现setter和getter这两种计算方法
3.枚举不可以有存储属性, 但是允许有计算属性
setter 对象.属性 = 值
getter var value = 对象.属性

struct Rect1 {
    var origion: (x: Double, y: Double) = (0, 0)
    var size: (w: Double, h: Double) = (0, 0)
    // 由于center的值是通过起点和宽高计算出来的, 所以没有必要提供一个存储属性
    // var center: (x: Double, y: Double) = (0, 0)
    var center: (x: Double, y: Double) {
        get{
            // print("get")
            return (origion.x + size.w/2, origion.y + size.h/2)
        }
        // set(newCenter){
        set{
            // print("set \(newCenter)")
            // 注意: 计算属性不具备存储功能, 所以不能给计算属性赋值, 如果赋值会发生运行时错误
            // 注意: setter可以自己传递一个参数, 也可以使用系统默认的参数newValue
            // 如果要使用系统自带的参数, 必须删除自定义参数
            // origion.x = newCenter.x - size.w / 2
            // origion.y = newCenter.y - size.h / 2
            origion.x = newValue.x - size.w / 2
            origion.y = newValue.y - size.h / 2
        }
    }
}
var r = Rect1()
r.origion = (0, 0)
r.size = (100, 100)
r.center = ((r.origion.x + r.size.w) / 2, (r.origion.y + r.size.h) / 2)
print("center.x = \(r.center.x) center.y = \(r.center.y)")
r.center = (100, 100)
print("origion.x = \(r.origion.x) origion.y = \(r.origion.y)")
print("center.x = \(r.center.x) center.y = \(r.center.y)")

只读计算属性
对应OC中的readonly属性, 所谓的只读属性就是只提供了getter方法, 没有提供setter方法

class Line2 {
    var start:Double = 0.0
    var end: Double = 0.0
    // 只读属性, 只读属性必须是变量var, 不能是常量let
    // 例如想获取长度, 只能通过计算获得, 而不需要外界设置, 可以设置为只读计算属性
    var length: Double{
        // 只读属性的简写, 可以省略get{}
        // get{
        return end - start
        // }
    }
}

var line2 = Line2()
line2.end = 100
print(line2.length)

属性观察器,类似OC中的KVO, 可以用于监听属性什么时候被修改, 只有属性被修改才会调用
有两种属性观察器:
1.willSet, 在设置新值之前调用
2.didSet, 在设置新值之后调用
可以直接为除计算属性和lazy属性之外的存储属性添加属性观察器, 但是可以在继承类中为父类的计算属性提供属性观察器
因为在计算属性中也可以监听到属性的改变, 所以给计算属性添加属性观察器没有任何意义

class Line3 {
    var start:Double = 0.0{
        willSet{
            print("willSet newValue = \(newValue)")
        }
        didSet{
            print("didSet oldValue = \(oldValue)")
        }
    }
    var end: Double = 0.0
}
var l = Line3()
l.start = 10.0 // "willSet newValue = 10.0\n" "didSet oldValue = 0.0\n"

类属性
在结构体和枚举中用static
在类中使用class, 并且类中不允许将存储属性设置为类属性

struct Person5 {
    // 普通的属性是每个对象一份
    var name: String = "solozyx"
    // 类属性是所有对象共用一份
    static var gender:String = "man"
    static var age:Int{
        return 99
    }
    func show()
    {
        print("gender = \(Person5.gender) name = \(name)")
    }
}

var p5 = Person5()
// print("gender = \(p.gender)") // 错误
print("gender = \(Person5.gender)")
var p6 = Person5()
// 类属性是所有对象共用一份
print("gender = \(Person5.gender)")
p5.show()
p6.show()
p5.name = "p5"
p6.name = "p6"
p5.name // "p5"
p6.name // "p6"
// 可以将计算属性设置为类属性
print("age = \(Person5.age)")
class Person6 {
    // 普通的属性是每个对象一份
    var name: String = "solozyx"
    // 类中不允许将存储属性定义为类属性
    // class var gender:String = "man" // 错误 使用 static
    // 类中只能将计算属性定义为类属性
    class var age:Int{
        return 99
    }
    func show()
    {
        print("age = \(Person6.age)")
    }
}
var p7 = Person6()
print("age = \(Person6.age)")
p7.show()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容