Properties(属性)
属性存储
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// the range represents integer values 0, 1, and 2
rangeOfThreeItems.firstValue = 6
// the range now represents integer values 6, 7, and 8
结构体FixedLengthRange存储了一个变量属性firstValue和常量属性。
常量属性和变量属性都可以在初始化是设置初始值,但是常量属性在初始化后就不能修改了。
常量属性存储结构体实例
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 属性
lazy属性在初始化时,不执行。在第一次使用时,才执行。
- lazy属性必须是变量,不能是常量。
class DataImporter {
/*
DataImporter is a class to import data from an external file.
The class is assumed to take a nontrivial 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
}
DataManager的属性data的数据来源方式有两种,一种是通过外部添加:
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// the DataImporter instance for the importer property has not yet been created
另一种是通过DataImporter导入,而DataImporter导入需要加载文件,因此把属性importer设置为lazy,在初始化时不加载文件,只有在第一次调用importer时,才开始加载文件:
print(manager.importer.filename)
// the DataImporter instance for the importer property has now been created
// Prints "data.txt"
计算属性
类,结构体,枚举除了储存属性外,你也可以定义计算属性(类似Java中的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)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// Prints "square.origin is now at (10.0, 10.0) "
简写setter声明
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)
}
}
}
Swift默认为setter提供newValue参数名。
只读的计算属性
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"
声明只读计算属性可以省略掉get
属性的监听
willSet和didSet,可以对除了lazy属性以外的任何属性使用:
- willSet存储值之前调用
- didSet值存储之后调用
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps
使用willSet 和 didSet对父类监听时,父类初始化完成后才能监听到
全局变量和本地变量
- 全局变量定义在方法,函数,闭包和类型之外
- 本地变量定义在方法,函数,闭包之内。
全局变量和本地变量都可以定义成计算属性,也可以使用willSet,didSet监听。
Type Properties(类型属性)
不需要实例化就可以访问的属性,类似Java的类中的静态属性。
类型属性的语法
使用static关键字在结构体,类,枚举中定义静态属性。
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 SomeClass {
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"