[Swift] 타입 캐스팅(Type Casting) - in / as 키워드
오늘은 타입 캐스팅에 관련해서 공부를 해보았다.
타입캐스팅은 두 연산자를 이용해서 사용한다.
- is 연산자를 사용해서 인스턴스의 타입을 확인
- as 연산자를 사용해서 같은 계층에 있는 다른 슈퍼클래스나 서브클래스로 취급하는 방법
예를 들어 Animal이라는 슈퍼클래스가 선언되어 있고, Human과 Fish라는 Animal을 상속받고 있는 서브클래스가 있다.
슈퍼클래스 Animal은 이름 변수를 가진 생성자를 하나 갖고 있고 각 서브클래스에는 고유의 함수를 하나씩 갖고 있다고 해보자.
class Animal {
var name: String
init(n: String){
name = n
}
}
class Human: Animal {
func code() {
print("Tying away...")
}
}
class Fish: Animal {
func breatheUnderWater(){
print("Breathing under water.")
}
}
그리고 각 클래스의 객체를 하나씩 선언해서 neighbours 라는 각각 다른 인스턴스 타입이 들어있는 객체 배열을 만들어주었다.
let julia = Human(n: "Julia Kim")
let jack = Human(n: "Jack Park")
let nemo = Fish(n: "Nemo")
let neighbours = [julia,jack,nemo]
1. Type Checking
is 키워드는 해당 인스턴스 타입이 맞는지 확인하려고 할 때 조건문과 함께 사용된다.
이 때 neighbours의 2번째 인스턴스 타입이 Human인지 확인하고 싶으면 is 를 사용해서 인스턴스 타입을 확인하면 된다.
밑에 예제는 nemo는 Fish 타입이기 때문에 아무것도 프린트 되지 않을 것이다.
if neighbours[2] is Human {
print("Human!")
}
2. Down Casting
니모(nemo)를 찾는 함수를 하나 선언했을 때, Animal 타입의 배열을 입력 받아 배열의 값들을 하나식 돌리면서 Fish 타입일 때 그 값의 name을 출력하도록 작성해보았다.
func findNemo(from animals: [Animal]){
for animal in animals {
if animal is Fish{
print(animal.name)
animal.breatheUnderWater //error!
}
}
}
그리고 Fish 타입의 animal을 찾았으니 Fish 클래스에서 선언해줬던 함수 breatheUnderWater() 를 호출도 해보았다.
error 발생이다!!!! 왜 그럴까?
아까 조건문과 is 연산자를 통해 Fish 타입을 찾은 animal 변수의 타입을 확인해보면 슈퍼클래스인 Animal 타입인 것을 알 수 있다.
그래서 error문에는 breatheUnderWater() 가 없다고 뜨는 것이다.
그러므로 Fish가 Animal에 속해있기 때문에(?) 상속 받고 있기 때문에,
Fish로 DownCasting 해줘야지 Fish 타입으로 변경된다.
이 때 사용하는 키워드가 as! 이다.
다운캐스팅을 하고 타입을 다시 확인해보면 Fish 인 것을 알 수 있다.
func findNemo(from animals: [Animal]){
for animal in animals {
if animal is Fish{
print(animal.name)
let fish = animal as! Fish //타입을 Fish로 다운 캐스팅 함 . Force downcasting
fish.breatheUnderWater()
}
}
}
다운캐스팅 하는 방법은 캐스팅 할 타입에 대한 확신(?) 에 따라 다르게 사용하면 될 것 같다.
- as? : 특정 타입이 맞는지 확신할 수 없을때 사용
- as! : 특정 타입이라는 것이 확실한 경우에 사용
let 새로운 변수 = <다운캐스팅 할 변수> as! <다운캐스팅 할 클래스>
3. Up Casting
다운 캐스팅의 반대는 ? 업 캐스팅이겠죠!!
서브 클래스의 타입을 슈퍼 클래스 타입으로 변경할 때 사용한다.
let animalFish = fish as Animal //UpCasting
4. Test
마지막으로 배열의 1번째 배열 값인 Human 타입의 jack을 Fish로 타입 변경하려고 시도해보자.
타입캐스팅 되지 않기 때문에 nil 이 들어있어 name 값을 출력하려 해도 아무 값도 없을 것이다.
let fish = neighbours[1] as? Fish //nil
fish?.name //nil
이 때 if - else 문을 이용해서 타입 캐스팅이 될 때만 해당 클래스의 메소드를 출력하고 아니면 실패 출력문을 작성해보았다.
결과는 안되기 때문에 실패 출력문이 출력 될 것이다~!
* 관련 자료 : Swift 공식 한국어 문서
타입캐스팅 (Type Casting) - The Swift Language Guide (한국어)
library가 갖고 있는 Movie,Song인스턴스의 공통 부모는 MediaItem이기 때문에 library는 타입 추론에 의해 [MediaItem] 배열의 형을 갖게 됩니다. library를 순회(iterate)하면 배열의 아이템은 Movie, Song 타입이
jusung.gitbook.io