함수가 일급시민으로서 상수나 변수에 함수참조를 할당할 수 있다. 그리고 이렇게 참조해두고 나중에 원할 때 호출할 수 있고, 다른 함수를 참조하도록 할 수도 있다.
func someFunction(paramA: Any, paramB: Any) {
print("someFunction called...")
}
var functionReference = someFunction(paramA:paramB:)
functionReference("A", "B")
functionReference = anotherFunction(paramA:paramB:)
프로퍼티도 이와 마찬가지로 값을 바로 꺼내오는 것이 아니라 어떤 프로퍼티의 위치만 참조하도록 할 수 있다. 바로 KeyPath를 활용하는 방법이다. 키 경로를 사용하여 간접적으로 특정 타입의 어떤 프로퍼티 값을 가리켜야 할지 미리 지정해두고 사용할 수 있다.
키 경로 타입은 AnyKeyPath라는 클래스로부터 파생된다. 제일 많이 확장된 키 경로 타입은 WritableKeyPath<Root, Value> 와 ReferenceWritableKeyPath<Root, Value> 타입이다. 전자는 값 타입에 키 경로 타입으로 읽고 쓸 수 있는 경우에, 후자는 참조 타입, 즉 클래스 타입에 키 경로 타입으로 읽고 쓸 수 있는 경우에 적용된다.
키 경로는 역슬래시, 타입, 마침표 경로로 구성된다.
\타입이름.경로.경로.경로
경로는 프로퍼티 이름으로 생각한다.
class Person {
var name: String
init(name: String) {
self.name = name
}
}
struct Stuff {
var name: String
var owner: Person
}
print(type(of: \Person.name)) ReferenceWritableKeyPath<Person, String>
print(type(of: \Stuff.name)) WritableKeyPath<Stuff, String>
키 경로는 기존의 키 경로에 하위 경로를 덧붙일 수 있다.
let keyPath = \Stuff.owner
let nameKeyPath = keyPath.appending(path: \.name)
각 인스턴스의 keyPath 서브스크립트 메서드에 키 경로를 전달하여 프로퍼티에 접근할 수 있다.
print(macbook[keyPath: \Stuff.name])