as
를 통해 타입 변경이 가능is
를 통해 타입 확인이 가능is
를 사용해서 타입을 확인하고 as
를 통해서 타입을 캐스팅 할 수 있다.
class Human {}
class Student: Human {}
var a = Human()
var b: Student = Human()
print(a is Human) // prints "true"
print(b is Human) // prints "true"
print(a is Student) // prints "false"
Human
타입과
Human
을 상속하는 Student
타입을 만들었다.
여기에서 a는 Human
타입의 인스턴스 이므로 is
를 통해보면 true
가 반환되고
Human
의 자식 타입인 Student
도 Human
타입으로 비교하면 true
가 반환된다.
하지만 Human타입인 a를 Student
냐고 물어보면 false
가 나온다.
Human
이 Student
타입보다 상위타입이라서 이런 결과가 나오는데
이해를 돕기위해 간단하게 예를 들어보면
1은 숫자이지만 숫자는 1이 아닌것과 같다.
숫자는 2, 3, 4, 5.. 등 이 있기 때문에 숫자 == 1 이라고 말할 수 없는 것이다.
우선 as
는 업캐스팅이고 as?, as!
는 다운캐스팅이다
as는 타입을 변경하는 것인데
하위타입에서 상위타입으로 올라가는 업캐스팅은 문제가 없이 잘 되는데
(1은 숫자가 될 수 있기 때문에!)
상위타입에서 하위타입으로 내려가는 다운캐스팅이 실패할 수 있다.
(위의 예시 처럼 숫자는 1이 될 수 없기 때문에!)
var a: Human = Human()
var b: Human = Student()
var c = b as Human
var d = c as! Student
Student -> Human 업캐스팅한 c는 Human타입이다
Human -> Student 다운캐스팅한 d는 이전의 Student 데이터를 가지고 있으므로 다운캐스팅이 실패하지 않는다
만약 Human타입을 상속하는 또 다른 타입이 있다면 그 타입으로 다운캐스팅은 실패할 것이다
데이터를 가지고 있지 않기 때문!
그래서 생겨난 것이 as?
, as!
이다
as? 는 옵셔널타입으로 다운캐스팅에 실패하면 nil
을 반환한다.
as! 는 강제성을 부여해주어서 다운캐스팅에 실패할 경우가 없을 경우에만 사용한다
하지만 언제나 그랬듯 이렇게 에러가 나면 에러체크가 힘드므로 왠만해선 as?를 사용하고
if let
이나 guard let
등으로 안전하게 사용하는 것이 좋을 것