저장 프로퍼티 | 계산 프로퍼티 |
값을 저장하고 있는 프로퍼티 | 값을 저장하고 있지 않고 특정하게 계산한 값을 반환해 주는 프로퍼티 |
클래스와 구조체에서만 사용 가능 | 클래스, 구조체, 열거형 모두에서 사용가능 |
저장 프로퍼티
let키워드를 이용해서 상수 혹은 var키워드를 이용해서 변수로 선언해 사용
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으로 선언하더라도 프로퍼티가 변경 가능
- 클래스 인스턴스는 참조 타입이기 때문
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// 범위 값은 0, 1, 2, 3 입니다.
rangeOfFourItems.firstValue = 6
// 에러 발생!
지연 저장 프로퍼티
- 값이 처음으로 사용 되기 전에는 계산되지 않는 프로퍼티
- 프로퍼티의 선언 앞에 lazy 키워드를 붙임
- 반드시 변수(var)로 선언해야 함
- 상수는 초기화가 되기전에 항상 값을 같는 프로퍼티인데, 지연 프로퍼티는 처음 사용되기 전에는 값을 갖지 않는 프로퍼티이기 때문
지연 저장 프로퍼티의 사용
- 프로퍼티가 특정 요소에 의존적이어서 그 요소가 끝나기 전에 적절한 값을 알지 못하는 경우
- 복잡한 계산이나 부하가 많이 걸리는 작업을 할 때 사용하면 실제 사용되기 전에는 실행되지 않아서 인스턴스의 초기화 시점에 복잡한 계산을 피할 수 있음
단일 스레드에서 사용할 때
- 초기화는 한 번만 수행됨
- 단일 스레드 환경에서는 처음으로 지연 프로퍼티에 접근하는 시점에 초기화가 수행되고, 이후에는 이미 초기화된 값이 반환됨
여러 스레드에서 접근할 경우
- 여러 스레드가 동시에 해당 지연 프로퍼티를 평가하여 초기화를 시도 가능 => 여러 번의 초기화가 발생할 수 있음
- 다중 스레드 환경에서 사용할 때는 동시 접근에 대한 동기화(Synchronization)를 고려해야 함
계산 프로퍼티
클래스, 구조체, 열거형에서 실제 값을 저장하고 있는 것이 아니라 getter와 optional한 setter를 제공해 값을 탐색하고 간접적으로 다른 프로퍼티 값을 설정할 수 있음
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)
}
}
}
읽기전용 계산 프로퍼티
getter만 있고 setter를 제공하지 않는 계산 프로퍼티
읽기전용 계산 프로퍼티는 반드시 반환 값을 제공하고 다른 값을 지정할 수는 없는 프로퍼티
주의!
계산된 프로퍼티를 선언시에는 반드시 let 이 아니라 var 로 선언해야함
보통 읽기전용(read-only)이라 함은 한번 값이 정해지면 변하지 않기 때문에 let 으로 선언하는 것이 맞으나 계산된 프로퍼티는 읽기전용(read-only)이라 하더라도 계산 값(width, height, depth 등)에 따라 값이 변할 수 있기 때문에 var 로 선언함
프로퍼티 옵저버
- 프로퍼티에는 새 값이 설정(set) 될 때마다 이 이벤트를 감지할 수 있는 옵저버를 제공 ,새 값이 이전 값과 같더라도 항상 호출됨
- 프로퍼티 옵저버는 지연 저장 프로퍼티에서는 사용할 수 없음
- 계산된 프로퍼티는 setter에서 값의 변화를 감지 할 수 있기 때문에 따로 옵저버를 정의할 필요가 없음
willSet
- 값이 저장되기 바로 직전에 호출
- willSet에서는 새 값의 파라미터명을 지정할 수 있는데, 지정하지 않으면 기본 값으로 newValue를 사용
didSet
- 새 값이 저장되고 난 직후에 호출
- 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")
}
}
}
}
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 → 새로운 값의 파라미터명으로 newTotalSteps를 지정해서 사용
- didSet → 변하기 전의 값을 의미하는 파라미터명을 지정하지 않고 oldValue라는 기본 파라미터명을 이용
전역변수와 지역변수
프로퍼티와 프로퍼티 옵저버 기능은 전역변수와 지역변수 모두에서 이용 가능
전역 변수
- 함수, 메소드, 클로저 혹은 타입 컨텍스트 밖에 정의된 변수
- 전역 상수와 변수는 lazy키워드를 붙일 필요 없이 지연 저장 프로퍼티처럼 지연 계산됨
지역 변수
- 함수, 메소드, 클로저 혹은 타입 컨텍스트 안에 선언된 변수
- 지역 상수와 변수는 지연 계산될 수 없음
타입 프로퍼티
- 타입 프로퍼티는 특정 타입에 속한 프로퍼티로 그 타입에 해당하는 단 하나의 프로퍼티만 생성
- 특정 타입의 모든 인스턴스에 공통으로 사용되는 값을 정의할때 유용함
주의!
타입 프로퍼티는 항상 초기값을 지정해서 사용해야함 → 타입 자체에는 초기자(Initializer)가 없어 초기화 할 곳이 없기 때문
타입 프로퍼티 구문
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 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"
타입 프로퍼티 장점
- 모든 인스턴스가 공유하는 값이기 때문에 메모리 사용을 효율적으로 관리 가능
- 인스턴스마다 중복된 값을 저장할 필요가 없기 때문에 메모리 절약 가능
- 모든 인스턴스가 동일한 타입 프로퍼티 값을 사용하기 때문에, 예상치 못한 값의 차이나 불일치 방지 가능
반응형
'⌨️ Language > swift' 카테고리의 다른 글
[Swift] 서브스크립트 (0) | 2024.03.22 |
---|---|
[Swift] 메서드 (0) | 2024.03.21 |
[Swift] 클래스와 구조체 (0) | 2024.03.19 |
[Swift] 클로저 (1) | 2024.03.18 |
[Swift] 예외 처리와 함수 (4) | 2024.03.17 |
댓글