1. 저장 속성
값이 저장되는 일반적인 속성
- 변수(var)나 상수(let)로 선언 가능하다
- 객체를 초기화할때 각 저장속성은 반드시 값을 가져야한다
(기본값 설정 또는 생성자에서 생성, 옵셔널타입으로 선언하여 nil을 초기값으로 하는게 가능하다)
class Person {
var name = "사람" // 저장속성(변수)
let age = "24" // 저장속성(상수)
init(name: String, age: Int) { // 초기화시 반드시 값을 가져야 한다
self.name = name
self.age = age
}
}
2. 지연 저장 속성
해당 속성의 초기화를 지연시킴
- 인스턴스가 초기화되는 시점에 해당 속성이 초기화되는게 아닌
해당 속성에 접근하는 순간에 개별적으로 초기화된다
--> 따라서 상수로 선언이 불가능하다 ( lazy let 불가능)
class Person {
var name = "사람" // 저장속성
lazy var age = "24" // 지연저장속성
// lazy let age = "24" // 지연저장속성은 상수로 선언이 불가능하다
init(name: String, age: Int) {
self.name = name
// self.age = age (생성자에서 초기화 하지 않는다)
}
}
var jimin = Person(name: "Jimin") // 인스턴스 생성시 age 속성 초기화 안된다
print(jimin.age) // 해당 속성에 접근하는 시점에 초기화된다
- 지연저장속성 사용 이유
1. 메모리공간을 많이 차지하는 속성을 저장할때 지연저장속성으로 선언( 메모리 낭비 막기위해, 해당 속성을 사용하지 않을경우 굳이 메모리에 다 올릴 필요가 없다.)
2. 다른 속성을 이용해야할때
class AView {
var num: Int
// 1. 메모리를 많이 차지할때 이 속성을 사용하지 않아도 되는경우
lazy var view = UIImageView()
// 2. 다른 속성을 이용해야할때
lazy var num2: Int = { return num * 10 }
init(num: Int) {
self.num = num
}
}
3. 계산속성
속성의 형태를 가진 실질적 메서드
- var로만 선언가능, 자료형 필수선언(형식추론 안됨)
- get블록은 필수구현이고 set블록은 선택구현이다(set블록만 구현하는건 불가능)
- set블록에서는 기본 파라미터 newValue가 제공되며 직접 파라미터 이름을 설정하는것도 가능하다
- get블록만 구현할시 get 블록 생략가능
var num1 = 50
var num2: Int {
get { // 필수구현
return num1 * 2
} set { // 선택적 구현
// 기본파리미터 newVlaue 제공( 원한다면 set(num) 이런식으로 파라미터 설정도 가능
num1 = newValue / 2
}
}
num2 // get블록 실행 -> 값가져오기 -> 100
num2 = 30 // set블록 실행 -> 값 세팅하기
num1 // 15
num2 // 30
var num3: Int {
return num * 3 // get블록만 구현시 get 생략가능
}
참고
// lazy var num: Int = {}() 이랑 var num: Int {}의 차이점
var num1 = 30
var num2: Int {
return num1 * 2
}
lazy var num3: Int = {
return num1 * 2
}()
num2 // 60
num3 // 60
num1 = 20
num2 // 40 (계산속성은 메서드 형식이기 때문에 항상 num1의 영향을 받는다)
num3 // 60 (초기화때에만 num1의 영향을 받는다)
// num2 = 20 (set블록을 구현하지 않으면 읽기전용이라 쓰기가 안된다)
num3 = 20 // (쓰기 쌉가능)
4. 타입속성
인스턴스에 속한 속성이 아닌 타입 자체에 속한 속성으로 내/외부에서 접근할때 Type.property로 접근해야한다
1) 저장타입속성
- 주로 저장타입속성을 사용한다
- 모든 인스턴스가 동일하게 가져야하는 속성이거나
모든 인스턴스가 공유해야하는 성격에 가까운 저장속성을 저장타입속성으로 선언
- static 키워드 사용. 재정의 불가능(class 키워드 사용 불가능)
- 상수, 변서 모두 선언 가능
- 항상 기본값 필요함(생성자에 의한 값설정 과정이 없으므로)
- 자체적으로 지연속성의 성격을 가짐
class Circle {
static let pi: Double = 3.14
// class let num: Int = 30 (저장타입속성은 class 키워드 사용불가 -> 상속시 재정의 불가능)
var radius: Double
init(radius: Double) {
self.radius = radius
Circle.pi // 내부에서도 타입으로 접근해야함
}
}
var circle1 = Circle(radius: 10.0)
circle1.radius
// circle1.pi (인스턴스에서 접근 불가능)
Circle.pi // 타입으로 접근가능, 인스턴스를 생성하지 않아도 접근이 가능함
3) 계산타입속성
- 상속시 재정의 가능 (class 키워드 사용시)
- 계산속성이기때문에 변수(var)만 사용 가능
class Circle {
static let pi: Double = 3.14
class var multiPi: Double {
return pi * 2
} // 상속시 재정의할려면 class 키워드 사용, 재정의가 필요 없을시 static키워드 사용가능
var radius: Double
init(radius: Double) {
self.radius = radius
Circle.pi // 내부에서도 타입으로 접근해야함
}
}
Circle.multiPi // 타입으로 접근
4. 속성감시자
저장속성의 변화시점을 관찰하는 실질적 메서드
- 저장속성 자체는 var로만 선언 가능 (상수는 변하지 않으므로 변화시점을 관찰하는 속성감사자가 필요없다)
- willSet 또는 didSet중 한가지만 구현하면 됨 (실질적으로 같은 기능, 주로 didSet 구현)
- 변수가 변하면, 업데이트 하는 패턴 구현할때 사용
- willSet - 새 값이 저장되기 직전에 호출
- didSet - 새 값이 저장된 직후에 호출
var num: Int = 10 {
willSet { // 기본파라미터 newValue 제공 (willSet(num) 식으로 파라미터 지정 가능
// 값이 변하기 직전에 호출
// 변경할 값이 파라미터에 주어짐
print("값이 \(num)에서 \(newValue)로 변합니다")
} didSet { // 기본파라미터 oldValue 제공 (didSet(num) 식으로 파라미터 지정 가능
// 값이 변한 직후에 호출
// 변하기 전의 값이 파라미터에 주어짐
print("값이 \(oldValue)에서 \(num)으로 변했습니다")
}
}
num = 20
/* 콘솔
값이 10에서 20로 변합니다
값이 10에서 20으로 변했습니다
*/