seong_hye, the developer

Swift) 문법 정리 - 타입 캐스팅(Type Casting) / Any, AnyObject 본문

IOS

Swift) 문법 정리 - 타입 캐스팅(Type Casting) / Any, AnyObject

seong_hye 2022. 7. 12.

타입 캐스팅이란?

인스턴스의 타입을 확인하거나 어떠한 클래스의 인스턴스를

해당 클래스 계층 구조의 슈퍼클래스나 서브 클래스로 취급하는 방법

 

- 메모리 값을 수정하는 것은 아님

- 단순히 해당 타입의 인스턴스인 것처럼 취급하려는 목적

class Person { var id = 0 ​​​​var name = "이름" ​​​​var email = "abc@gmail.com" } class Student: Person { var studentId = 1 } class Undergraduate: Student { var major = "전공" } let person = Person() let student = Student() let undergraduate = Undergradutae()

is 연산자

타입에 대한 검사를 수행하는 연산자 (이항연산자)

참이면 true / 거짓이면 false

 

~>  상속관계의 하위 클래스는 상위 클래스를 포함하고 있기 때문에 true

 

person is Person //true person is Student //false person is Undergraduate //false student is Person //true student is Student //true student is Undergraduate //false undergraduate is Person //true undergraduate is Student //true undergraduate is Undergraduate //true

as 연산자

인스턴스의 타입의 힌트를 변경하는 연산자

 

업캐스팅(Upcasting) - as 타입

하위클래스의 메모리 구조로 저장된 인스턴스를 상위 클래스 타입으로 인식

타입 캐스팅 항상 성공

상호 호환가능한 타입도 항상 성공

 

// 업캐스팅 let student2 = student as Person let undergraduate2 = undergraduate as Student

 

다운캐스팅(Downcasting) - as? / as!

상위클래스의 메모리 구조로 저장된 인스턴스를 하위 클래스 타입으로 인식

실패할 수도 있기때문에, 두 가지 연산자 존재

          

as?

- 성공: Optional 타입으로 리턴 -> 필요한 경우, 언래핑 필요

- 실패: nil 리턴

as!

- 성공: Optional 타입을 강제 언래핑한 타입

- 실패: 런타임 오류

 

다운캐스팅 성공에 대한 확신이 있을 때는 as! 를 사용, 그렇지 않을 경우엔 as? 를 사용

if-let 구문을 통해 as? 연산자로 다운캐스팅하고 반환된 옵셔널 값을 처리하는 방법 (일반적인 방법)

 

// 다운캐스팅 // 3개 변수를 가진 항목(person)이 // 5개 변수를 가진 항목(undergraduate)에 접근하려고 함 let person2 = person as? Undergraduate print(person2) //nil if let newPerson = person as? Undergraduate { print("hello newPerson") }

 

++ Swift 타입과 Objective-C 타입 간은 as를 사용

(내부적으로 완전히 상호 호환이 가능하도록 설계)

~> 여전히 Objective-C 기반의 프레임워크를 사용중이기 때문에 


코딩을 하다보면 어떤 타입으로 반환하거나 제공해야하는 지 헷갈리는 경우가 생김

이런 경우를 위해 스위프트에서는 불특정한 타입을 다룰 수 있는 타입을 제공함

Any

기본 타입(Int, String, Bool,...), 커스텀 클래스, 구조체, 열거형, 함수타입까지도 포함해서

어떤 타입의 인스턴스도 표현할 수 있는 타입 (옵셔널 타입도 포함)

 

var anySomthing: Any = "Swift" anySomthing = 10 anySomthing = 3.3

 

Any 타입은 옵셔널 타입을 포함한 모든 타입을 나타낼 수 있기 때문에

저장된 타입의 메모리 구조를 알 수 없어서 항상 타입캐스팅을 해야함

 

let array: [Any] = ["Swift", 5, 4,56, Person()] for item in array { if let item as? String { ‌​​​​print(item) ​​​​} }

 

AnyObject

어떤 클래스 타입의 인스턴스도 표현할 수 있는 타입

 

let objArray:[AnyObject] = [Person(), Student(), NSString()] (objArray[0] as! Person).name //"이름"

 

Any / AnyObject은 switch문에서 is / as 패턴을 사용해서 분기 처리 가능

 

for (index, item) in array.enumerated() { ​​​​switch item { ​​​​case is Int: // item is Int ​​​​​​​​print("Index - \(index): 정수입니다.") ​​​​case let num as Double: // let num = item as Double ​​​​​​​​print("Index - \(index): 소수 \(num)입니다.") ​​​​case is String: // item is String ​​​​​​​​print("Index - \(index): 문자열입니다.") ​​​​case let person as Person: // let person = item as Person ​​​​​​​​print("Index - \(index): 사람입니다.") ​​​​​​​​print("이름은 \(person.name)입니다.") ​​​​​​​​print("나이는 \(person.age)입니다.") ​​​​case is (String) -> String: // item is (String) -> String ​​​​​​​​print("Index - \(index): 클로저 타입입니다.") ​​​​default: ​​​​​​​​print("Index - \(index): 그 이외의 타입입니다.") ​​​​} }

의도적인 옵셔널값의 사용

Any는 모든 타입을 포함하므로, 의도적인 옵셔널값을 사용하려면 Any타입으로 변환하면

  컴파일러가 알려주는 경고를 없앨 수 있음

 

let optionalNumber: Int? = 3 print(optionalNumber) // 경고 print(optionalNumber as Any) // 경고 없음

왜 사용할까?

옵셔널값은 임시적인 값일 뿐이므로, 일반적으로 개발자들은

옵셔널 바인딩을 해서 언래핑해서 안의 값을 사용해야함

  (Any로 변환하겠다는 것은 그 자체를 사용하겠다는 의미임 ==> 경고 없음)

 

 

++ Any나 AnyObject로 선언하기 보다 예상되는 타입을 구체적으로 지정하는 것이 더 좋음 


참고자료)

https://onelife2live.tistory.com/9

https://zrr.kr/qNHN

'IOS' 카테고리의 다른 글

Swift) 문법 정리 - 프로토콜  (0) 2022.07.12
Swift) 문법 정리 - 튜플  (0) 2022.07.12
Swift) 문법 정리 - 상속  (0) 2022.07.12
Swift) 문법 정리 - 속성(Property) & 함수(Method)  (0) 2022.07.12
Swift) 문법 정리 - 연산자  (0) 2022.07.12
Comments