본문 바로가기
iOS/Swift 문법 심화 학습

타입캐스팅

by 황민우 2022. 1. 26.

정의

타입 캐스팅은 인스턴스의 타입을 확인 하는 "is"연산자와 

해당 인스턴스를 수퍼 클래스 또는 하위 클래스로 취급하는 "as" 연산자가 있으며,

"as" 연산자는 사용 목적에 따라 업 캐스팅과 다운 캐스팅으로 나뉩니다.


is

  타입 체크를 목적으로 사용하는 연산자입니다.

  런타임 시점에서 구현되며, True와 False 값이 반환됩니다.

 

형식

표현식 is Type

 

예제1

let A: Int = 10
let B = A is String
let C = A is Int
print(B)	// False
print(C)	// True

 

  예제2

   또한, 상속에서 활용하는 경우

   표현식에 대한 Type이 서브클래스인지, 특정 Type으로 캐스팅 되는지 체크하는 기능으로도 사용됩니다.

class Man { }
class Student: Man { }

let Minho: Student = .init()
let A = Minho is Student
let B = Minho is Man

print(A,B)	// True True

as : Type Casting

  표현식이 특정 Type으로 캐스팅된다면, 상속 관계에서 as키워드를 통해 업 캐스팅과, 다운 캐스팅을 할 수 있습니다.

  또한, Any와 AnyObject 타입을 통해 상속 관계가 아니여도 예외적으로 캐스팅을 구현할 수 있습니다.

 

as 연산자의 종류

as 컴파일 단계에서 캐스팅 : 업 캐스팅 기능
as? 런타임 단계에서 캐스팅 : 다운 캐스팅 기능
as! 런타임 단계에서 강제 캐스팅 : 다운 캐스팅 기능

 


업 캐스팅

  정의 

      서브 클래스 인스턴스를 "수퍼 클래스의 타입"으로 참조합니다.

      업 캐스팅은 항상 성공합니다.

 

  예제

Man, Student, Major라는 3개의 클래스가 있고 Student, Major 클래스는 Man클래스를 상속받은 상태입니다.

  Major 타입의 인스턴스를 생성해, 이를 Man타입으로 업 캐스팅해서 상수 A에 저장시켰습니다.

-

  상수 A를 통해 수퍼 클래스인 Man 클래스의 멤버 name을 출력시켰을 땐, Minwoo라는 값이 오류없이 출력됩니다.

  하지만, 똑같은 조건으로 상수 A를 통해 수퍼 클래스인 Man 클래스를

 상속받는 Major클래스의 멤버 subject를 출력시켜 보면 Crash가 발생합니다.

-

  예제를 통해 Man 클래스의 멤버인 name엔 접근이 가능하지만,

  서브 클래스 Major의 멤버인 subject에는 접근 할 수 없다는 것을 알 수 있습니다.

  즉, 업 캐스팅은 서브 클래스의 인스턴스를 수퍼 클래스의 타입으로만 참조할 수 있습니다.

 

class Man {
    let name: String = "Minwoo"
}
class Student: Man { 
    let grade: Int = 2
}
class Major: Man{
    let subject: String = "Swift"
}
let A = Major.init() as Man
print(A.name)
print(A.grade)

다운 캐스팅

정의

다운 캐스팅은 업 캐스팅의 반대 개념입니다.

수퍼 클래스에 대한 참조가 아닌, 하위 클래스에 대한 참조의 목적으로 사용됩니다.

느낌표(!)와 물음표(?)를 as 뒤에 붙여, 다운 캐스팅의 실패 확률이 있을 경우 as? 로 사용하고

실패확률이 없을 경우 as! 로 강제 캐스팅할 수 있습니다.

 

예제

이전과 동일한 예제입니다.

직전에는 Major 타입의 인스턴스를 Man 클래스로 업캐스팅하여 상수 A에 저장했습니다.

이번에는 Man 타입으로 업 캐스팅된 A를 다시 Major 클래스로 다운캐스팅해, 변수 B에 저장하겠습니다.

그리고 변수 B를 통해 Man 클래스의 멤버와 Major 클래스의 멤버를 출력해봤더니 모두 오류없이 출력됩니다.

-

이는 다운 캐스팅을 통해 서브클래스 즉, 하위 클래스의 멤버에 접근할 수 있게 된 것입니다. 

class Man {
    let name: String = "Minwoo"
}
class Student: Man { 
    let grade: Int = 2
}
class Major: Man{
    let subject: String = "Swift"
}
let A = Major.init() as Man
print(A.name)			// Minwoo
var B: Major = A as! Major
print(B.subject)		// Swift
print(B.name)			// Minwoo

 

마무리

as! 를 통해 다운캐스팅을 실패했을 때는 Crash가 발생하니 주의해야합니다.

as? 를 통해 다운캐스팅을 실패했을 때는 nil값이 반환되기 때문에

Optional Type으로 선언해 비교적으로 안전하게 접근할 수 있습니다.

 


내용출처

https://babbab2.tistory.com/127

https://www.youtube.com/watch?v=sIKESw-qa8k 

 

'iOS > Swift 문법 심화 학습' 카테고리의 다른 글

값 타입과 참조 타입  (0) 2022.01.31
extensions  (0) 2022.01.30
guard  (0) 2022.01.28
assert  (0) 2022.01.28
Initializer  (0) 2022.01.27

댓글