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

你可能感兴趣的:(swift5 基本语法-存储属性和计算属性)