<aside> 💡 클래스, 구조체, 열거형과 관련한 값입니다. 프로퍼티의 종류에는 저장 프로퍼티(Stored Properties)와 계산된 프로퍼티(Computed Properties)가 있습니다. 저장 프로퍼티는 말 그대로 값을 저장하고 있는 프로퍼티이고, 계산된 프로퍼티(Computed properties)는 값을 저장하고 있지 않고 특정하게 계산한 값을 반환해 주는 프로퍼티입니다. 계산된 프로퍼티(Computed properties)는 클래스, 구조체, 열거형 모두에서 사용가능하지만, 저장 프로퍼티는 클래스와 구조체에서만 사용 가능합니다. 추가로 프로퍼티 옵저버를 정의해서 값이 변할 때마다 모니터링할 수 있습니다.
</aside>
<aside>
💡 단순히 값을 저장하고 있는 프로퍼티 입니다. 이 프로퍼티는 let
키워드를 이용해서 상수 혹은 var
키워드를 이용해서 변수로 선언해 사용할 수 있습니다.
구조체/클래스 모두 해당 (열거형은 선언을 할수가없음)
클래스/구조체의 틀에서 찍어낸 각 인스턴스가 가지는 고유의 데이터 저장 공간
변수(var)나 상수(let)로 선언 가능
객체의 초기화시, 각 저장 속성은 반드시 값을 가져야 함
(기본값 설정하거나 또는 생성자에서 설정, 또는 옵셔널 타입으로 선언하여 nil을 초기값으로 갖는 것 가능)
(열거형의 경우 따로 메모리 공간이 필요한 저장 속성(데이터)은 선언할 수 없음)
</aside>
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// 범위 값은 0, 1, 2 입니다.
rangeOfThreeItems.firstValue = 6
// 범위 값은 6, 7, 8 입니다.
구조체를 상수로 선언하면(let) 그 구조체 인스턴스의 프로퍼티를 변경할 수 없습니다.
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// 범위 값은 0, 1, 2, 3 입니다.
rangeOfFourItems.firstValue = 6
// 에러 발생!
<aside>
💡 rangeOfFourItems
는 상수(let
)로 선언되었기 때문에 프로퍼티를 변경할 수 없습니다.
반면 구조체가 아니라 클래스는 let
으로 선언하더라도 프로퍼티가 변경 가능합니다.
이유는 클래스 인스턴스는 참조 타입 이기 때문입니다.
</aside>
<aside>
💡 지연 저장 프로퍼티는 값이 처음으로 사용 되기 전에는 계산되지 않는 프로퍼티입니다.
지연 저장 프로퍼티로 선언하기 위해서는 프로퍼티의 선언 앞에 lazy
키워드를 붙이면 됩니다.
지연 프로퍼티는 반드시 변수(var
)로 선언해야 합니다. 왜냐하면 상수는 초기화가 되기전에 항상 값을 같는 프로퍼티인데, 지연 프로퍼티는 처음 사용되기 전에는 값을 갖지 않는 프로퍼티이기 때문입니다.
why? 지연저장속성을 사용하는가 지연 프로퍼티는 프로퍼티가 특정 요소에 의존적이어서 그 요소가 끝나기 전에 적절한 값을 알지 못하는 경우에 유용합니다. 또 복잡한 계산이나 부하가 많이 걸리는 작업을 지연 프로퍼티로 선언해 사용하면 실제 사용되기 전에는 실행되지 않아서 인스턴스의 초기화 시점에 복잡한 계산을 피할 수 있습니다.
만약 지연 프로퍼티가 여러 스레드에서 사용되면 지연 프로퍼티가 한번만 실행되는 걸 보장하지 않습니다. 만약 지연 프로퍼티가 단일 스레드에서 사용되면 초기화는 한번만 하게 됩니다.
</aside>
class DataImporter {
/*
DataImporter는 외부 파일에서 데이터를 가져오는 클래스입니다.
이 클래스는 초기화 하는데 매우 많은 시간이 소요된다고 가정하겠습니다.
*/
var filename = "data.txt"
// 데이터를 가져오는 기능의 구현이 이 부분에 구현돼 있다고 가정
}
class DataManager {
lazy var importer = DataImporter()
var data = [String]()
// 데이터를 관리하는 기능이 이 부분에 구현돼 있다고 가정
}
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// DataImporter 인스턴스는 이 시점에 생성돼 있지 않습니다.
print(manager.importer.filename)
// the DataImporter 인스턴스가 생성되었습니다.
// "data.txt" 파일을 출력합니다.
DataManager
라는 클래스를 선언하고 이 클래스는 데이터를 가져오는 DataImporter
클래스를 갖고 있습니다. 그리고 이 DataImporter
는 실제 디스크 파일에서 데이터를 가져오기 때문에 초기화시 많은 시간이 소요됩니다. 그래서 이 클래스를 지연 프로퍼티(lazy var importer = DataImporter()
) 로 선언합니다. 이 프로퍼티는 코드에서 볼 수 있듯 DataManager
인스턴스 manager
를 생성하고 거기에 data 를 넣어도 그 시점에 DataImporter
인스턴스는 생성돼 있지 않습니다. 다시 말하면 지연 프로퍼티로 선언해 놓았기 때문에 실제 그 프로퍼티를 사용하기 전에는 복잡하고 시간일 오래 소요되는 연산을 할 필요가 없다는 것입니다.
manager.importer.filename
가 실행돼 실제 importer
프로퍼티에 처음 접근할 때 비로소 importer
인스턴스는 생성됩니다.
<aside> 💡 따라서, 생성자에서 초기화를 시키지 않기 때문에 "선언시점에 기본값을 저장"해야함
</aside>
만약 지연 프로퍼티가 여러 스레드에서 사용되면 지연 프로퍼티가 한번만 실행되는 걸 보장하지 않습니다. 만약 지연 프로퍼티가 단일 스레드에서 사용되면 초기화는 한번만 하게 됩니다.