【Swift4.0】属性
翻译能力有限,如有不对的地方,还请见谅!希望对Swift的学习者有所帮助,使用的编写工具:JQNote InNote(iPhone)
属性是把值和某个类,结构体或者枚举联系在一起。存储型属性存储一个实例的常量和变量值部分,然而计算型属性会计算出(而不是存储)一个值。类,结构体和枚举都支持计算型属性,而存储型属性只有类和结构体支持。这两种属性通常跟某个类型的实例关联。然而,属性也可以跟类型本身关联起来,这种属性称之为类型属性。另外,你可以定义一个属性观察者来检测该属性值的改变。
存储属性
一个存储属性是一个常量或者变量,被存储作为一个类或者结构体实例的一部分。你可以在定义它的时候给它一个缺省值,也可以在初始化方法中设置和修改存储属性的初始化值,即便是该存储属性是常量。如果你创建了一个常量结构体实例,那么就不能修改该实例的属性,即使属性被声明为变量。
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// this range represents integer values 0, 1, 2, and 3
rangeOfFourItems.firstValue = 6
// this will report an error, even though firstValue is a variable property”
因为结构体是值类型,当一个结构体实例被声明为常量,那么它的所有属性都不能被改变。但是对于类来说,是引用类型,如果类实例被声明为常量,你还可以改变它的变量属性的。
懒存储属性
这种属性直到它第一次被使用才会初始化。在声明存储属性前面加上lazy关键字就表示为懒存储属性。
你必须总是声明懒存储属性为变量(var),因为直到实例初始化完成之后,它的初始化值可能不能被获取,而常量属性必须总是在实例初始化完成之前有一个值。
class DataImporter {
/*DataImporter is a class to import data from an external ”
“file.
The class is assumed to take a non-trivial amount of time to initialize.
*/
var filename = "data.txt"
// the DataImporter class would provide data importing functionality here
}
class DataManager {
lazy var importer = DataImporter()
var data = [String]()
// the DataManager class would provide data management functionality here
}
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")”
如上面的例子,因为importer 被声明为一个lazy 属性,DataImporter实例仅仅是当 importer属性第一次被调用获取的时候,才会创建。
print(manager.importer.filename)
// the DataImporter instance for the importer property has now been created
// Prints "data.txt”
计算型属性
计算型属性实际上不会存储一个值,相反,它们提供了一个getter和一个可选的setter方法来直接获取或者设置其它属性的值。
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var width = 0.0, height = 0.0
}
struct Rect {
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(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
}
var square = Rect(origin: Point(x: 0.0, y: 0.0),
size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0)
只读的计算型属性
一个计算型的属性,如果只有getter方法,没有setter方法,那就被认为是一个只读的计算属性。你可以声明一个简单的只读计算属性,不需要get关键字:
struct Cuboid {
var width = 0.0, height = 0.0, depth = 0.0
var volume: Double {
return width * height * depth
}
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// Prints "the volume of fourByFiveByTwo is 40.0”
属性观察者
属性观察者观察和响应一个属性值的改变。当属性值每次被set的时候,观察者都会被调用,即使新的值和当前的值相同。除了lazy属性,你可以将属性观察者添加到任何存储属性:
>> willSet :值被存储之前调用
>> didSet :新值被存储之后调用
当你实现了willSet,它会传递一个新的值作为一个常量参数。你也可以给这个参数特定一个名字。如果你没有写这个参数名,那么默认newValue可以被使用。类似,如果实现了didSet,你也可以特定一个参数名或者使用默认的oldValue。
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
类型属性
实例属性属于某个类型的实例,每次在创建实例的时候,它有自己的一系列属性。与其它实例是分开的。
你也可以定义属于类型自己的属性,而不属于每个该类型的实例。类型属性只会拷贝一次,无论该类型被创建了多少个实例。
不像存储实例属性,存储类型属性必须赋一个缺省值,这是因为类型自己没有一个初始化器可以在初始化的时候给类型属性设置值。
定义一个类型属性,使用staic关键字:
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 var overrideableComputedTypeProperty: Int {
return 107
}
}
获取和设置类型属性:
print(SomeStructure.storedTypeProperty)
// Prints "Some value."
SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty)
// Prints "Another value."
print(SomeEnumeration.computedTypeProperty)
// Prints "6"
print(SomeClass.computedTypeProperty)
// Prints "27”