Swift4-属性
2018-08-09 本文已影响99人
wingsrao
属性
1.你必须把延迟存储属性声明为变量(使用 var 关键字),因为它的初始值可能在实例初始化完成之前无法取得。常量属性则必须在初始化完成之前有值,因此不能声明为延迟。
延迟存储属性的初始值在其第一次使用时才进行计算。你可以通过在其声明前标注 lazy 修饰语来表示一个延迟存储属性。
class DataImporter {
var fileName = "data.txt"
}
class DataManager {
lazy var importer = DataImporter()
}
//如果被标记为 lazy 修饰符的属性同时被多个线程访问并且属性还没有被初始化,则无法保证属性只初始化一次。
2.简写设置器(setter)声明
//如果一个计算属性的设置器没有为将要被设置的值定义一个名字,那么他将被默认命名为 newValue
struct AlternativeRect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set {
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
}
}
3.只读计算属性
struct Cuboid {
var width = 0.0, height = 0.0, depth = 0.0
var volume: Double {
return width * height * depth
}
}
4.属性观察者
- willSet 会在该值被存储之前被调用。
- didSet 会在一个新值被存储后被调用。
父类属性的 willSet 和 didSet 观察者会在子类初始化器中设置时被调用。它们不会在类的父类初始化器调用中设置其自身属性时被调用。
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) { //newValue
print("About to set totalSteps to \(newTotalSteps)")
}
didSet { //oldValue
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
如果你以输入输出形式参数传一个拥有观察者的属性给函数, willSet 和 didSet 观察者一定会被调用。这是由于输入输出形式参数的拷贝入拷贝出存储模型导致的:值一定会在函数结束后写回属性。
5.全局常量和变量永远是延迟计算的,与延迟存储属性有着相同的行为。不同于延迟存储属性,全局常量和变量不需要标记 lazy 修饰符。
6.类型属性:
不同于存储实例属性,你必须总是给存储类型属性一个默认值。这是因为类型本身不能拥有能够在初始化时给存储类型属性赋值的初始化器。
存储类型属性是在它们第一次访问时延迟初始化的。它们保证只会初始化一次,就算被多个线程同时访问,他们也不需要使用 lazy 修饰符标记。
使用 static 关键字来开一类型属性。对于类类型的计算类型属性,你可以使用 class 关键字来允许子类重写父类的实现。
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 1
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 6
}
}
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 27
}
//使用 class 关键字来允许子类重写父类的实现
class var overrideableComputedTypeProperty: Int {
return 107
}
}