일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 제어전송문
- copy-on-write
- class
- 파스칼표기법
- 코드스니펫
- 주간 달력
- IOS
- unrecognized selector sent to class
- error해결
- avaliable
- AnyObject
- Switch
- ios 개발 강의
- 생명주기
- K디지털기초역량훈련
- uikit
- struct
- actionSheet
- 다짐글
- 바이트디그리
- 내_삶
- 연관값
- SWIFT
- 글또
- 회고
- Git
- MyLife
- weekly calendar
- On branch is up to date with ' '
- 글또9기
- Today
- Total
seong_hye, the developer
Swift) 문법 정리 - 타입 캐스팅(Type Casting) / Any, AnyObject 본문
타입 캐스팅이란?
인스턴스의 타입을 확인하거나 어떠한 클래스의 인스턴스를
해당 클래스 계층 구조의 슈퍼클래스나 서브 클래스로 취급하는 방법
- 메모리 값을 수정하는 것은 아님
- 단순히 해당 타입의 인스턴스인 것처럼 취급하려는 목적
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로 선언하기 보다 예상되는 타입을 구체적으로 지정하는 것이 더 좋음
참고자료)
'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 |