이 포스팅은 Swift 시리즈 20 편 중 4 번째 글 입니다.
목차
프로퍼티
- 앞에서 배운 내용인데, 좀 더 명확하게 구분해보자.
프로퍼티의 종류
- 역할에 따른 분류
- 인스턴스 프로퍼티
- 타입 프로퍼티
- 종류
- 저장 프로퍼티
- 연산 프로퍼티
var
로만 선언 가능- 읽기 전용 구현은 가능 -
get
블록을 작성 - 쓰기 전용 구현은 불가능
위의 4가지가 섞여서 존재할 수 있다. 즉 4가지의 가능성이 존재.
- 인스턴스 저장 프로퍼티
- 타입 저장 프로퍼티
- 인스턴스 연산 프로퍼티
- 타입 연산 프로퍼티
프로퍼티의 정의
- 구조체, 클래스, 열거형 내부에 구현이 가능
- 열거형에는 연산 프로퍼티만 구현 가능
- 읽기 쓰기 모두가능하게 하려면
get
블럭과set
블럭 모두 구현- 읽기 전용으로 만들고 싶으면
get
만 구현
- 읽기 전용으로 만들고 싶으면
set
에서 암시적 매개변수 newValue를 사용할 수 있음
struct Student {
// 인스턴스 저장 프로퍼티
var name: String = ""
var `class`: String = "Swift"
var koreanAge: Int = 0
// 인스턴스 연산 프로퍼티
var westernAge: Int {
get {
return koreanAge - 1
}
set(inputValue) {
koreanAge = inputValue + 1
}
}
// 타입 저장 프로퍼티
static var typeDescription: String = "학생"
// 읽기 전용 타입 연산 프로퍼티
// 읽기 전용이 default라 적지 않으면 읽기전용이라고 판단함
static var selfintroduction: String {
return "학생타입입니다."
}
}
- 인스턴스 저장 프로퍼티는 일반적이니 패스
- 인스턴스 연산 프로퍼티는, 특정값을 받아서 다른 저장 인스턴스의 값을 설정해줘야 한다거나 다른 프로퍼티로 부터 연산을 통해 해당 프로퍼티의 값이 도출될 때 주로 사용
- 타입 저장 프로퍼티는 기존에 알고 있던 타입 프로퍼티
- 타입 연산 프로퍼티 역시 비슷하다.
이러한 방법을 사용하면 기존의 introduce와 같은 함수를 읽기 프로퍼티를 사용하여 대체하는 것도 가능
// 인스턴스 생성
var wansik: Student = Student()
wansik.name = "wansik"
wansik.koreanAge = 20
// 인스턴스 저장 프로퍼티 사용
print(wansik.name) // wansik
// 인스턴스 연산 프로퍼티 사용
print(wansik.westernAge) // 19
// 타입 저장 프로퍼티 사용
print(Student.typeDescription) // 학생
// 타입 연산 프로퍼티 사용
print(Student.selfintroduction) // "학생타입입니다."
연습
struct Money {
var currencyRate: Double = 1100
var dollar: Double = 0
var won: Double {
get {
return dollar * currencyRate
}
set(newValue) {
dollar = newValue/currencyRate
}
}
}
var moneyInMyPocket = Money()
// 인스턴스 연산 프로퍼티에 쓰기 시도
moneyInMyPocket.won = 11000
print(moneyInMyPocket.won) // 11000
print(moneyInMyPocket.dollar) // 11
// 인스턴스 연산 프로퍼티에 읽기 시도
moneyInMyPocket.dollar = 10
print(moneyInMyPocket.won) // 11000
- 이렇게 연산 프로퍼티는 두개 이상의 입력으로 프로퍼티를 설정할 수 있을 떄, 서로 다른 두개의 프로퍼티가 관계를 가지고 있는 경우, 한번의 할당으로 두 개 이상의 프로퍼티를 할당할 수 있다.
프로퍼티 감시자
- 프로퍼티 감시자를 사용하면 프로퍼티 값이 변경될 때, 원하는 동작을 수행할 수 있음
- 값이 변경되기 직전에 willSet 블럭이, 변경 직후 didSet 블럭이 호출됨
- 변경되려는 값이 기존 값과 같더라도 항상 동작
willSet
블럭에서 암시적 매개변수newValue
를 사용 가능didSet
블럭에서는oldValue
를 사용 가능- 프로퍼티 감시자는 연산 프로퍼티에서 사용 불가
- 함수, 메서드, 클로저, 타입 등의 지역/전역 변수에 모두 사용 가능
struct Money {
// 프로퍼티 감시자 사용
var currencyRate: Double = 1100 {
willSet(newRate) {
print("환율이 \(currencyRate)에서 \(newRate)으로 변경될 예정입니다")
}
didSet(oldRate) {
print("환율이 \(oldRate)에서 \(currencyRate)으로 변경되었습니다")
}
}
// 매개 변수를 암시적으로 newValue, oldValue를 갖는다.
var dollar: Double = 0 {
willSet {
print("\(dollar)달러에서 \(newValue)달러로 변경될 예정입니다")
}
didSet {
print("\(oldValue)달러에서 \(dollar)달러로 변경되었습니다")
}
}
// 연산 프로퍼티
var won: Double {
get {
return dollar * currencyRate
}
set {
dollar = newValue / currencyRate
}
// get, set과 함께 사용이 불가함
// willSet {
// print("원화의 값이 \(won)으로 변경될 예정입니다.")
// }
// didSet {
// print("원화의 값이 \(won)으로 변경되었습니다.")
// }
}
}
var moneyInMyPocket = Money()
// 환율이 1100.0에서 1150.0으로 변경될 예정입니다
moneyInMyPocket.currencyRate = 1150.0
// 환율이 1100.0에서 1150.0으로 변경되었습니다
//0.0달러에서 10.0달러로 변경될 예정입니다
moneyInMyPocket.won = 11500
//0.0달러에서 10.0달러로 변경되었습니다
print(moneyInMyPocket.dollar) // 10