블로그

[Swift] Type Casting

게시 4분

다른 언어에서는 대부분 타입 캐스팅을

'자료형의 변환'

이라고 생각하지만, Swift는 하나 더 있다.
Swift에서 Type Casting은 다음 두가지 의미를 가진다.

① 인스턴스의 타입 확인 … 2가지 방법
② 자료형의 변환(업캐스팅, 다운캐스팅) … 3가지 방법

  1. 인스턴스의 타입 확인
class Machine class IPhone: Machine class Galuxy: Machine

두 클래스 Machine, IPhone, Galuxy가 있다고 할 때,
IPhone, Galuxy 는 Machine을 상속한다.

이 때 두 변수가 있다고 하자.

var machine: machine = Machine() var iPhone_6: IPhone = IPhone() var galuxy_2s: Galuxy = Galuxy()

이 때 다음과 같은 타입확인이 가능하다

1번 방식 print(machine is Machine) // True print(machine is IPhone) // False print(machine is Galuxy) // False print(iPhone_6 is Machine) // True print(iPhone_6 is IPhone) // True print(iPhone_6 is Galuxy) // Fasle 2번 방식 print(type(of: machine) == Machine.self) // True print(type(of: machine) == IPhone.self) // False print(type(of: machine) == Galuxy.self) // False print(type(of: iPhone_6) == Machine.self) // True print(type(of: iPhone_6) == IPhone.self) // True print(type(of: iPhone_6) == Galuxy.self) // Fasle
  1. 자료형변환
var i: Int = 3 var f: Float = Float(i)

다음과 같은 코드를 보고 이미 타입캐스팅을 알고있는거 아니냐 생각할 수 있지만,
놀랍게도 저 코드들은 자료형변환도 아니고, 타입캐스팅도 아니다.

Float이라는 이름을 가진 구조체의 이니셜라이저다.
즉, 타입을 바꾼게 아니라 새로운 인스턴스를 만든거다.

또한 자료형 변환을 위해 as, as!, as? 세 가지를 사용한다.

(1) 업캐스팅

var machine: Machine = IPhone()

업캐스팅은 as 를 사용해 처리해주며,
자식의 인스턴스가 부모 인스턴스로 변환되는것이다.
machine 변수는 IPhone 인스턴스가 Machine 인스턴스로 변환되어 저장된다.
그리고 이는 아래 코드와 완전히 동일하다.

var machine: Machine = IPhone() as Machine

as Machine이 생략된것이고, '컴파일러가 알아서 처리해준다.'

(2) 다운캐스팅

업캐스팅의 반대로, 부모 인스턴스가 자식 인스턴스로 변환된다.
컴파일러가 자동으로 처리하지 않기에, 우리가 처리할 줄 알아야한다.
다운캐스팅은as!, as?로 처리해준다.

!과, ?에 옵셔널에서 사용했던 의미가 그대로 담긴다.
as!로 캐스팅되는건 우리가 일반적으로 생각하는
A as! B하면 A가 B로 변환된다고 생각하면 된다.
하지만 변환에 실패하면 에러가 발생한다.

A as? B를 하면 옵셔널로 변환된 결과를 반환하기에 타입 확인까지 가능하며,
개발자가 실수할 여지를 줄여주고 if let을 통해 nil처리가 가능하다.

즉, as!은 생각하던대로 사용하면 되고
as?는 if let으로 nil 예외처리 해주면서 사용하면 된다.

class Machine { var a = 1 var b = 2 } class IPhone: Machine { var c = 3 } var machine1: Machine = IPhone() var machine2 = Machine() if let iphone = machine1 as? IPhone { print(iphone.c) // 출력 } else { print("no no") } if let iphone = machine2 as? IPhone { print(iphone.c) } else { print("no no") // 출력 } print((machine1 as! IPhone).c) // 출력 성공 print((machine2 as! IPhone).c) // ERROR!

machine1에서 타입이 Machine이라 변수 c에 접근할 수 없다.
하지만 변수 c에 접근해야하는 상황이 꽤 생긴다. 이럴 때는 IPhone으로 형변환 해줘야한다.

하지만 machine2와 같이 원래 객체가 Machine()이라면, nil이 반환되고 no no가 출력된다.

마지막 as! 부분도 같은 논리로 생각하면 된다.

댓글

댓글을 남기면 닉네임(또는 GitHub 계정 정보)이 저장됩니다. 개인정보처리방침

GitHub