swift5 基本语法-存储属性和计算属性

swift中跟实例相关的属性可以分为2大类。
1. 存储属性(Stored Property)
1.1 相当于成员变量的概念;
1.2 存储在实例的内存中;
1.3 结构体和类可以定义存储属性;
1.4 枚举【不可以】定义存储属性;

2. 计算属性(Computed Property)
2.1 本质就是方法(函数);
2.2 不占用实例的内存;
2.3 枚举、结构体、类都可以定义计算属性;

struct Circle {
   //存储属性-半径
   var radius : Double
   //计算属性-直径
   var diameter : Double {
       set{
           radius = newValue / 2
       }
       get {
           radius * 2
       }
   }
}

1.存储属性(Stored Property)

存储属性可以是变量存储属性(用关键字var定义),也可以是常量存储属性(用关键字let定义)。
在创建【】或【结构体】的实例时,必须为所有的存储属性设置一个合适的初始值。

例:

01.png

解决这个报错,有以下几种方法
方法一:】 可以再初始化器里为存储属性设置一个初始值;

struct Point {
   var x: Int
   var y: Int
   init() {
       x = 10
       y = 20
   }
}
var p1 = Point()

方法二:】 可以分配一个默认的属性作为属性定义的一部分

struct Point {
    var x: Int = 10
    var y: Int = 20
}
var p1 = Point()
2. 计算属性(Computed Property)

计算属性不直接存储值,而是提供一个 getter 来获取值,一个可选的 setter 来间接设置其他属性或变量的值。
如果计算属性的 setter 没有定义表示新值的参数名,则可以使用默认名称 newValue。

例:

struct Circle {
   //存储属性-半径
   var radius : Double
   //计算属性-直径
   var diameter : Double {
       set{
           radius = newValue / 2
       }
       get {
           radius * 2
       }
   }
}

只读计算属性
只有 getter 没有 setter 的计算属性就是只读计算属性。
例:

struct Circle {
   //存储属性-半径
   var radius : Double
   //计算属性-直径
   var diameter : Double {
       get {
           radius * 2
       }
   }
}

【注意】
① 只读计算属性总是返回一个值,可以通过点(.)运算符访问,但不能设置新的值。

02.png

② 不能只有set 而没有get
03.png

* 拓展

【 延迟存储属性(Lazy Stored Property) 】

延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。
在属性声明前使用 lazy 来标示一个延迟存储属性。

例1:lazy var car = Car()

class Car {
   init() {
       print("Car init")
   }
   func run() -> Void {
      print("Car is running~")
  }
}

class Person {
   lazy var car = Car()
   init() {
       print("Person init!")
   }
   func goOut() -> Void {
       car.run()
   }
}
let p = Person()
print("----------")
p.goOut()

输出结果如下:

Person init!
----------
Car init
Car is running~

根据输出结果我们得知,当我们创建Person对象的时候,let p = Person(),暂时没有用到car的属性,所以不会调用car的初始化方法,此时只会打印Person init!语句,和----------,接着会执行p.goOut(),因为goOut()里面有car对象,所以此时会调用car对象的初始化方法,打印Car initCar is running~

例2:var car = Car() 没有lazy属性修饰

class Car {
   init() {
       print("Car init")
   }
   func run() -> Void {
      print("Car is running~")
  }
}

class Person {
  var car = Car()
   init() {
       print("Person init!")
   }
   func goOut() -> Void {
       car.run()
   }
}
let p = Person()
print("----------")
p.goOut()

输出结果如下:

Car init
Person init!
----------
Car is running~

由两个例子对比我们可以知道,lazy修饰的对象,可以延迟对象的创建

注意:
必须将延迟存储属性声明成变量(使用var关键字),因为属性的值在实例构造完成之前可能无法得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。

【 属性观察器( Property Observer) 】

可以为除了延迟存储属性(非lazy)之外的其他存储属性添加属性观察器.

例:

struct Circle {
   //存储属性-半径
   var radius : Double {
       willSet {
          print("willSet",newValue)
       }
       didSet {
           print("didSet",oldValue,radius)
       }
   }
   
   init() {
       self.radius = 1.0
      print("Circle init~~")
   }
}

var circle = Circle()
circle.radius = 5.5
print(circle.radius)

运行结果如下:

Circle init!
willSet 5.5
didSet 1.0 5.5
5.5

【 小结:】
可以为属性添加如下的一个或全部观察器:

① willSet在设置新的值之前调用,默认交newValue
② didSet在新的值被设置之后立即调用,默认叫oldValue
③willSet和didSet观察器在属性初始化器过程中不会被调用

【 全局变量和局部变量 】

属性观察器、计算属性功能 ,同样可用于全局变量、局部变量。

① 全局属性


///全局属性
var number: Int {
   get {
       return 10
   }
   set {
       print("setNumber",newValue)
   }
}
number = 20 //setNumber 20
print(number) //getNumber 10

② 局部属性

///局部属性
func testFunc() {
   var age = 10 {
       willSet {
           print("willSet",newValue)
       }
       didSet {
           print("didSet",oldValue,age)
       }
   }
   age = 11
   //willSet 11
   //willSet 10 11
}
testFunc()
【 类型属性( Type Property) 】

使用关键字 static 来定义值类型的类型属性,关键字 class 来为类定义类型属性。

使用static修饰 static var count : Int = 0

04.png

  • 类型属性(Type Property)只能通过类型去访问
    ① 存储类型属性(Stored Type Property):整个程序运行过程中,只有一份内存(类似于全局变量)
    存储类型属性默认是lazy,会在第一次使用的时候才初始化;
    ② 计算类型属性(Computed Type Property)
  1. 可以通过static定义属性类型
    例:
struct Shape {
   var width : Int = 0
   static var count : Int = 0
}
var s = Shape()

Shape.count = 10
print(Shape.count)
  1. 如果是类,可以用关键字class
    例:
class Shape {
   var width : Int = 0
   class var count : Int {
       return 0
   }
}
var s = Shape()

print(Shape.count)

【 小结:】
1.如果是struct定义的类型,使用class来修饰是不可以的,会报错,只能用static来修饰

05.png

正确的写法:

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

推荐阅读更多精彩内容