Properties(프로퍼티)는 클래스, 구조체, 열거형에서 사용되는 associate value입니다. Stored property(저장 프로퍼티)는 클래스, 구조체, 열거형의 인스턴스의 일부로 저장되고 Computed property(계산 프로퍼티)는 값을 계산하는데 쓰입니다. 저장 프로퍼티는 클래스와 구조체에만 제공되고 계산 프로퍼티는 클래스, 구조체, 열거형에 제공됩니다.
a stored property is a constant or variable that’s stored as part of an instance of a particular class or structure.
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
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로 변수를 선언해야 합니다. 변수가 아닌 상수로 선언하게 되면 처음 사용할 때까지 값이 없게 되기 때문에 오류를 발생하게 됩니다.
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
}
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// the DataImporter instance for the importer property hasn't yet been created
print(manager.importer.filename)
// the DataImporter instance for the importer property has now been created
// Prints "data.txt"
DataManager의 importer 프로퍼티가 lazy 프로퍼티로 선언되었습니다. 그런 뒤 manager라는 이름으로 새로운 DataManager 상수 인스턴스를 생성하게 되는데 위의 코드에서는 아직 importer가 사용되지 않았습니다. 이런 상태에서 importer 프로퍼티에 값이 할당되면 낭비이기 때문에 이럴 때를 위해 importer를 lazy 프로퍼티로 선언해서 낭비를 줄일 수 있습니다.
??
다른 프로퍼티를 기반으로 동작하는 계산 속성.
계산 프로퍼티는 클래스, 구조체, 열거형에서 사용 가능합니다. 계산 프로퍼티에는 값을 직접적으로 저장하지 않는 대신 getter와 setter를 사용해서 다른 프로퍼티와 값들을 간접적으로 접근할 수 있습니다. 이때 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)"
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)
}
}
}
struct CompactRect {
var origin = Point()
var size = Size()
var center: Point {
get {
Point(x: origin.x + (size.width / 2),
y: origin.y + (size.height / 2))
}
set {
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
}
}
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"
Property observers observe and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value. 초기화를 꼭 해야 한다!
You can add property observers in the following places:
Property wrapper는 프로퍼티 저장 방법을 관리하는 코드와 프로퍼티를 정의하는 코드를 구분하는 계층을 추가하는 것입니다. 예를 들어 스레드 안전성 검사나 데이터를 DB에 저장하는 프로퍼티가 있는 경우 모든 프로퍼티에 대해 코드를 작성해야 하는데 Property wrapper를 사용하면 이러한 작업을 줄일 수 있습니다. 관리 코드를 한 번만 작성한 다음 여러 프로퍼티에 적용하여 관리 코드를 재사용할 수 있기 때문입니다.
You can also define properties that belong to the type itself, not to any one instance of that type. There will only ever be one copy of these properties, no matter how many instances of that type you create. These kinds of properties are called type properties.