Swift 属性
Swift 4语言为类、枚举或结构提供了与值相关联的属性。属性可以进一步分为存储属性和计算属性。
存储属性和计算属性之间的区别
| 存储属性 | 计算属性 | 
|---|---|
| 将常量和变量值存储为实例 | 计算值而不是存储值 | 
| 由类和结构体提供 | 由类、枚举和结构体提供 | 
存储属性和计算属性都与实例类型相关联。当属性与其类型的值相关联时,它被定义为“类型属性”。存储和计算属性通常与特定类型的实例相关联。但是,属性也可以与类型本身相关联。这样的属性被称为类型属性。还可以使用属性观察器
- 观察存储属性的值
 - 观察从超类派生的子类的属性
 
存储属性
Swift 4引入存储属性的概念来存储常量和变量的实例。常量的存储属性由’let’关键字定义,变量的存储属性由’var’关键字定义。
- 在定义中,存储属性提供“默认值”
 - 在初始化过程中,用户可以初始化和修改初始值
 
struct Number {
   var digits: Int
   let pi = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.pi)")
当我们使用playground运行上面的程序时,我们得到以下结果-
67
3.1415
考虑上述代码中的以下行-
let pi = 3.1415
在这里,变量pi被初始化为一个具有实例pi = 3.1415的存储属性值。因此,只要引用该实例,它将仅保留值3.1415。
另一种具有存储属性的方法是将其作为常量结构体。因此,整个结构体实例将被视为“存储在常量中的属性”。
struct Number {
   var digits: Int
   let numbers = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7
当我们使用playground运行上面的程序时,我们得到以下结果:
error: cannot assign to 'numbers' in 'n'
n.numbers = 8.7
而不是将’number’重新初始化为8.7,它将返回一个错误消息,指示’number’被声明为常量。
延迟存储属性
Swift 4提供了一个灵活的属性,称为’延迟存储属性’,它在变量第一次被初始化时不计算初始值。在变量声明之前使用’lazy’修饰符将其声明为延迟存储属性。
延迟属性用途 −
- 延迟对象的创建。
 - 当属性依赖于类的其他部分,而这些部分暂时未知时
 
class sample {
   lazy var no = number()    // `var` declaration is required.
}
class number {
   var name = "Swift 4"
}
var firstsample = sample()
print(firstsample.no.name)
当我们在playground上运行上述程序时,我们得到以下结果−
Swift 4
实例变量
在Objective-C中,存储属性也有实例变量用于备份目的,以存储在存储属性中声明的值。
Swift 4将这两个概念整合到了一个单一的“存储属性”声明中。与具有相应实例变量和备份值的存储属性不同,“存储属性”包含了有关变量属性的所有整合信息,包括变量名、数据类型和内存管理功能,并且它们都在一个单一的位置进行定义。
计算属性
计算属性不会存储值,而是提供一个getter和一个可选的setter来间接检索和设置其他属性和值。
class sample {
   var no1 = 0.0, no2 = 0.0
   var length = 300.0, breadth = 150.0
   var middle: (Double, Double) {
      get {
         return (length / 2, breadth / 2)
      }
      set(axis){
         no1 = axis.0 - (length / 2)
         no2 = axis.1 - (breadth / 2)
      }
   }
}
var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)
print(result.no1)
print(result.no2)
当我们在playground上运行上述程序时,我们得到以下结果-
(150.0, 75.0)
-150.0
-65.0
当计算属性将新值保留为未定义时,将为该特定变量设置默认值。
计算属性作为只读属性
在计算属性中,只读属性被定义为具有getter但没有setter的属性。它始终用于返回一个值。变量可以通过“.”语法进一步访问,但不能被设置为另一个值。
class film {
   var head = ""
   var duration = 0.0
   var metaInfo: [String:String] {
      return [
         "head": self.head,
         "duration":"\(self.duration)"
      ]
   }
}
var movie = film()
movie.head = "Swift 4 Properties"
movie.duration = 3.09
print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)
当我们在playground上运行上述程序时,我们会得到以下结果 –
Swift 4 Properties
3.09
使用计算属性作为属性观察者
在Swift 4中,可以使用属性观察者来观察和响应属性值的变化。每当设置属性的值时,属性观察者会被调用。除了懒加载存储属性外,我们还可以通过方法“重写”将属性观察者添加到“继承”的属性中。
属性观察者可以通过以下方式定义:
- 在存储值之前 – willset
 - 
在存储新值之后 – didset
 - 
在初始化程序中设置属性时,无法调用willset和didset观察者。
 
class Samplepgm {
   var counter: Int = 0 {
      willSet(newTotal){
         print("Total Counter is: \(newTotal)")
      }
      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}
let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800
当我们在playground上运行上述程序时,我们得到以下结果 –
Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700
本地和全局变量
为计算和观察属性而声明的本地和全局变量。
| 本地变量 | 全局变量 | 
|---|---|
| 定义在函数、方法或闭包上下文中的变量。 | 在函数、方法、闭包或类型上下文之外定义的变量。 | 
| 用于存储和检索值。 | 用于存储和检索值。 | 
| 存储属性用于获取和设置值。 | 存储属性用于获取和设置值。 | 
| 还使用计算属性。 | 还使用计算属性。 | 
类型属性
属性在类型定义部分使用大括号 {} 进行定义,变量的范围也在此之前定义。对于值类型的类型属性,使用 ‘static’ 关键字;对于类类型的类型属性,使用 ‘class’ 关键字。
语法
struct Structname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}
enum Enumname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}
class Classname {
   class var computedTypeProperty: Int {
      // return an Int value here
   }
}
查询和设置属性
就像实例属性一样,类型属性使用’.’语法来查询和设置,只需在类型本身上使用,而不是指向实例。
struct StudMarks {
   static let markCount = 97
   static var totalCount = 0
   var InternalMarks: Int = 0 {
      didSet {
         if InternalMarks > StudMarks.markCount {
            InternalMarks = StudMarks.markCount
         }
         if InternalMarks > StudMarks.totalCount {
            StudMarks.totalCount = InternalMarks
         }
      }
   }
}
var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()
stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks)
stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)
当我们在playground上运行上述程序时,我们得到以下结果 −
97
87
极客教程