Swift를 쓰다 보면 NSArray나 NSMutableArray 같은 Objective-C 기반 클래스를 만날 때가 있다.
특히 다른 프레임워크나 레거시 코드랑 연동할 때 자주 보이는데…
func changeTheArray(_ array: NSArray) {
let copy = array as! NSMutableArray
}
이런 코드 보면 한 가지 궁금증이 생긴다.
NSArray 타입인데 왜 NSMutableArray로 바꿀 수 있는 걸까?
사실 Swift에서 NSArray는 "불변" 배열이고,
NSMutableArray는 "가변" 배열이다.
근데 이 둘은 클래스 계층상 관계가 있다.
NSMutableArray는 NSArray의 하위 클래스다.
즉, NSMutableArray는 자동으로 NSArray로 업캐스팅되고,
필요하면 다시 as!나 as?를 써서 다운캐스팅할 수 있는 거다.
이 코드를 보자.
let someNames = NSMutableArray(array: ["Foo", "Bar"])
func changeTheArray(_ array: NSArray) {
let copy = array as! NSMutableArray
copy.add("Baz")
}
changeTheArray(someNames)
print(someNames) // ["Foo", "Bar", "Baz"]
여기서 핵심은 이거다:
함수 인자는 NSArray지만 실제 객체는 NSMutableArray이기 때문에 캐스팅이 가능하다.
그리고 중요한 사실 하나!
NSMutableArray는 참조 타입이라, 함수 내부에서 추가한 값이 밖에서도 반영된다.
NSArray는 불변 배열이고, NSMutableArray는 그 하위 클래스인 가변 배열이다.NSArray로 받아도, 실제로는 NSMutableArray일 수 있으니 as!로 다운캐스팅이 가능하다.NSMutableArray는 참조 타입이라 내부 값을 바꾸면 원본도 바뀐다.let으로 선언해도 인스턴스 내부 수정은 막지 않는다.NSMutableArray는 NSArray로 업캐스팅되었다가 다운캐스팅으로 다시 가변 배열처럼 쓸 수 있다. 하지만 항상 타입 확인을 하고 안전하게 써야 한다.
