프로퍼티 옵저버 (Property Observer)
- 프로퍼티 옵저버는 프로퍼티를 관찰하여 특정 프로퍼티의 값 변경 전후에 추가 동작을 수행할 수 있다
- 저장 프로퍼티 (Stored Propety), 연산 프로퍼티 ( Computed Property)에서만 사용 가능.
willset
- willset은 프로퍼티 값이 변경되기 직전에 호출, newValue를 통해 변경될 값 접근 가능.
didset
- didset은 프로퍼티 값이 변경된 직후에 호출, oldValue를 통해 변경되기 전의 값 접근 가능.
willset vs didset
- 둘 다 작성이 되어 있는 경우, 당연히 willset 먼저 호출
var temp = 10 {
willSet{
print("값이 \(newValue) 로 변경될 예정입니다.")
}
didSet {
print("값이 \(oldValue)에서 \(temp) 로 변경되었습니다.")
}
}
temp = 20
타입 캐스팅 (Type Casting)
- 변수나 객체의 타입을 다른 타입으로 변환하는게 타입 캐스팅이다.
is
- 변수나 객체의 타입을 체크하는 연산자, 반환값은 boolean이다.
let integer : Int = 30
let boolean : Bool = true
let array : [String] = []
print(integer is Int)
print(boolean is String)
print(array is [String])
- 깊게 생각해야 할 점은, 만약 특정 인스턴스가 자식 클래스의 타입을 갖고 있고, 부모클래스로 is로 확인을 하여도, true를 반환한다.
let integer : Int = 30
print(integer is Int)
print(integer is Any)
as, as!, as?
- 인스턴의 타입을 확인하거나, 해당 인스턴스를 슈퍼 클래스 (부모 클래스)나 하위 클래스 (자식 클래스)로 취급하는 방법
- 상속관계에서의 인스턴스과 타입의 대한 정리가 필요하다
class Person {
}
class Student: Person {
}
let person: Person = Person() - 가능
let person: Student = Person() - 불가능
let student: Person = Student() - 가능
let student: Student = Student() - 가능
- 위 코드는 Person 이 부모 클래스이며, Student가 자식 클래스다. 자식 클래스의 인스턴스는 부모 클래스의 타입을 갖을 수 있으나, 부모 클래스의 인스턴스는 자식 클래스의 타입을 갖을 수 없다.
- 예시에서의 코드를 쉽게 설명하자면, 학생을 사람으로 취급할 수 있지만, 모든 사람을 학생으로 취급할 수 없다. 뭐 이런식으로 접근하면 편할꺼 같다. 물론 이건 해당 예시에서만 가능한 생각방밥이지만.
- 아래 표를 보고 as, as?, as!의 차이를 알아보자.
연산자 | 실행단계 | 반환 값 | 캐스팅 방향 |
---|
as | 컴파일 단계 | 인스턴스 or Fail | 업 캐스팅 |
as? | 런타임 단계 | 옵셔널 타입 인스턴스 or nil | 다운 캐스팅 |
as! | 런타임 단계 | 인스턴스 or Runtime Error | 다운 캐스팅 |
- 아래 예시 코드를 통해 조금 더 이해가 될 수 있다.
class Person {
var id = 0
var name = "name"
var email = "hgk@gmail.com"
}
class Worker: Person {
var salary = 300
}
class Programmer: Worker {
var lang = "Swift"
}
let person1 = Person()
let worker1 = Worker()
let programmer1 = Programmer()
let personList : [Person] = [person1, worker1, programmer1]
personList[1].name
print(type(of: personList[0]))
print(type(of: personList[1]))
print(type(of: personList[2]))
let temp1 = personList[1] as Person
let temp3 = personList[1] as! Worker
if let temp5 = personList[1] as? Worker {
print(temp5.salary)
}