Swift

기초 문법 타입 캐스팅

pockpock 2024. 6. 12. 17:19
타입 캐스팅

자, 타입 캐스팅이 뭘까?

타입 캐스팅이란 인스턴스의 "타입"을 확인 하거나, 해당 인스턴스를 슈퍼 클래스나 하위 클래스로 취급하는 방법이다.

 

여기서 타입이란?

  • 기본 데이터 타입(Int, Double, String, Bool 등등)
  • 옵셔널(Optional)
  • 커스텀 데이터 타입(struct, class, enum, protocol 등)

자 이제, 코드를 통해 알아보자.

 

1) is

  • is 연산자는 타입을 체크하는 연산자. 비교 결과를 bool 타입으로 반환한다.
  • 예시 코드
let char: Character = "A"

print(char is Character)
// 출력값: true
print(char is String)
// 출력값: false

let bool: Bool = true

print(bool is Bool)
// 출력값: true
print(bool is Character)
// 출력값: false

 

 

위 처럼 표현식이 Type과 동일하거나, 표현식이 Type의 서브 클래스인 경우 -> true, 아닐 경우 -> false 반환

is 연산자는 타입을 체크하는 연산자로, 반환 값은 Bool형태이다.

 

Xcode로 직접 실행해보면,

1. is 실제 적용

이런식으로 친절하게 알려준다. 중간중간 타입 테스트를 해볼 때 유용할 것 같다.

 

자. 위에서 표현식 Type의 서브 클래스인 경우도 언급을 했었는데, 예제코드를 확인해보자.

class Human {  }
class Teacher: Human { }

let teacher: Teacher = .init()
teacher is Teacher // true
teacher is Teacher // true

 

이렇게 Teacher 클래스가 Human클래스를 상속 받았을 때,

teacher이란 인스턴스는 Human클래스의 서브 클래스 이기 때문에

다음과 같이 true라는 결과가 나오는 것 이다.

 

다음으로 넘어가기 전, 타입캐스팅에 대해 알아보니 업캐스팅과 다운캐스팅에 대해 먼저 짚고 넘어가야 할 것 같다.

업캐스팅이란, 서브 클래스의 인스턴스를 슈퍼 클래스의 타입으로 참조하는 것을 업캐스팅 이라고 한다.

근데, 찾아보니 업캐스팅은 항상 성공한다 라고 명시되어 있다.

음.. 아직 배우는 단계라 안 와닿는데.. 하다보면 이해할 수 있겠지..!?

 

업캐스팅

애플 예제를 응용해서 한번 살펴보자

class Human {
	let name: String
    init(name: String){
    	self.name = name
    }
}
class Teacher: Human {  }
class Student: Human {  }

let people: [Human] = [
	Teacher.init(name: "강선생"),
	Student.init(name: "윤제자"),
	Student.init(name: "김제자")
]

 

이 코드를 봤을 때 Human 클래스를 상속 받는 서브 클래스 Teacher, Student가 각각 존재.

그리고 people이란 배열에, teacher, student 인스턴스 들이 담겨져있음.

Swift는 타입에 민감하다. 그런데 어떻게 두 가지 타입의 인스턴스가 저장될 수 있을까?

가능한 이유는 바로 이전에 배운 업캐스팅 때문이다.

 

부모 클래스가 같다 -> 즉, 둘의 부모 클래스가 Human클래스로 동일하기 때문에,

Human 클래스로 업캐스팅 해서 묶어버린 것.

 

업캐스팅은 '항상 타입 캐스팅이 성공'하기 때문에

as도 사용이 가능하다.

// as를 사용한 업캐스팅
let human = Teacher.init() as Human

이런식으로! 추가로 as의 설명을 덧붙이자면,

  • as
    • as 연산자는 컴파일 단계에서 캐스팅이 실행된다. 따라서 항상 타입 캐스팅이 성공할 경우에만 사용할 수 있다. -> 업캐스팅
    • 캐스팅에 실패할 경우 에러가 발생한다.
    • 캐스팅하려는 타입이 같은 타입 이거나 부모클래스 타입이라는 것을 알 때 as 연산자를 사용한다.

요런 느낌이다!

 

 

자, 그럼 다음으로 다운캐스팅에 대해서 알아볼까?

다운캐스팅

 

다운 캐스팅은 부모 클래스 인스턴스를 서브 클래스의 타입으로 참조한다.

업캐스팅된 인스턴스를 다시 원래 서브 클래스 타입으로 참조할 때 사용한다.

다운 캐스팅은 실패할 수 있기 때문에 as? , as! 연산자를 사용한다.

 

2) as!, as?

  • as?
    • as? 연산자는 런타임에 캐스팅이 실행된다.
    • 성공하면 옵셔널 타입의 인스턴스를 반환하고 실패하면 nil을 반환한다.
    • 실패할 가능성이 있으면 as?를 사용하는 것이 좋다. -> 다운캐스팅
  • as!
    • as! 연산자는 런타임에 특정 타입으로 강제 캐스팅한다.
    • 강제 타입 캐스팅에 실패할 경우 런타임 에러가 발생할 수 있다. -> 다운캐스팅
    • 캐스팅에 성공한 경우 인스턴스를 반환한다.(옵셔널 x)

마지막으로 성공 예시 코드를 확인해보고 마무리하자.

for human in people {
   if let teaher =  human as? Teacher {
        print("강선생 : \(teacher.name)")
    } else if let student =  human as? Student {
        print("윤제자  : \(student.name)")
    }
}

 

정리 끄으으으으읕~~ 빨리 문법 마스터 하고싶다 ㅠㅠ