[Swift 기초] 타입캐스팅

2022. 4. 4. 10:28Swift 기초 정리

728x90

//공부 기록용 포스팅입니다. 틀린 부분이 있을 경우 댓글로 알려주시면 감사합니다! 😎

 

 

 

  • 타입캐스팅은 인스턴스의 타입을 확인하는 용도(is)
  • 클래스의 인스턴스를 부모 혹은 자식 클래스의 타입으로 사용할 수 있는 지 확인하는 용도(as)

0. 참고

let someInt: Int = 100
let someDouble: Double = Double(someInt)
  • 타입캐스팅이 아니라 → someInt라는 값을 가지고 Double 타입의 값을 하나 더 생성해주는 것

타입 캐스팅 예제를 위한 클래스 정의

class Person {
    var name: String = ""
    func breath(){
        print("숨을 쉽니다.")
    }
}

class Student: Person {
    var school: String = ""
    func goToSchool(){
        print("학교를 갑니다.")
    }
}

class UniversityStudent: Student{
    var major: String = ""
    func freeFriday(){
        print("대학생은 금공강이지!")
    }
}

//인스턴스 생성
var p: Person = Person()
var s: Student = Student()
var u: UniversityStudent = UniversityStudent()

1. 타입 확인 - is

//is를 사용해서 타입을 확인 - 연산의 결과는 true/false
var result: Bool

result = p is Person  //true
result = p is Student //false
result = p is UniversityStudent //false

    //Student는 Person 클래스를 상속받았기 때문에 Person의 특성을 가지고 있음
result = s is Person  //true
result = s is Student  //true
result = s is UniversityStudent  //false

    //UniversityStudent는 Student를 상속받고, Person도 상속받음
result = u is Person  //true
result = u is Student  //true
result = u is UniversityStudent  //true
  • is를 사용해서 타입을 확인할 수 있다. 연산의 결과는 true / false
    • Type과 동일하거나 Type의 서브클래스 인 경우 true
    • 그 외 false
  • 상속에 유의해야 함

1-1. 타입확인 switch - case

  • 상속과 관련된 클래스는 switch문의 순서에 주의해야 한다.
if p is UniversityStudent {
    print("p는 대학생입니다.")
}else if p is Student{
    print("p는 학생입니다.")
}else if p is Person{
    print("p는 사람입니다.")
} //p는 사람입니다.

switch s{
case is Person:
    print("s는 사람입니다.")
case is Student:
    print("s는 학생입니다.")
case is UniversityStudent:
    print("s는 대학생입니다.")
}  //s는 사람입니다.

1-2. 타입 캐스팅 - as

  • 변환할 type과 호환된다면 변환할 type으로 캐스팅된 인스턴스를 리턴한다.

2. 업 캐스팅 - as

  • as를 사용하여 부모 클래스의 인스턴스로 사용할 수 있도록 컴파일러에게 타입정보를 전환
    • 서브 클래스 → 슈퍼 클래스
    • 하위 클래스(sub class)는 항상 상위 클래스의 부분집합 이므로 언제나 성공
  • Any혹은 AnyObject로도 타입정보를 변환할 수 있다.
  • 암시적으로 처리되기 때문에 생략해도 무방하다.
//Person 타입으로 선언했더라도 (실질적으로) UniversityStudent 타입으로 할당할 수 있다.//Person 타입으로 선언했더라도 UniversityStudent 타입으로 생성할 수 있다.
var p2: Person = UniversityStudent() as Person
var s2: Student = Student()
//어떤 타입도 가능하다.
var a: Any = Person()  //as Any 암시적으로 생략 가능
  • UniversityStudent 타입의 인스턴스 p2를 생성하지만, 이를 Person 타입으로 업캐스팅해서 p2에 저장하겠다.

3. 다운 캐스팅 - as? 또는 as!

  • as? 또는 as! 를 사용하여 자식 클래스의 인스턴스로 사용할 수 있도록 컴파일러에게 인스턴스 타입 정보를 전환
    • 슈퍼 클래스 → 서브 클래스
  • 업케스팅을 한 변수만 다운케이스팅을 할 수 있는건가? 에 대한 야곰님의 답변
    • 업 캐스팅 하여 저장(혹은 전달)된 인스턴스는 향후 다운 캐스팅에 성공할테고, 그렇지 않은 인스턴스는 다운 캐스팅 시도 때 실패하겠죠. as? 를 사용하면 성공 or 실패를 할 수 있고, as! 를 사용하면 성공때는 문제 없지만 실패하면 프로그램이 죽어버립니다. 다운캐스팅하려는 대상이 업 캐스팅 된 상태인지 항상 알 수는 없기 때문에 ! 는 사용을 지양하는게 좋겠죠.

3-1. 조건부 다운 캐스팅 - as?

  • 런타임 시점에 타입 캐스팅을 하며, 실패할 경우 nil을 리턴
  • 반환 타입이 옵셔널 타입
// p2는 실질적으로 할당된 인스턴스가 UniversityStudent이기 떄문에 
// Person 타입으로 선언했어도 UniversityStudent로 다운 캐스팅 할 수 있다.
// 캐스팅에 성공할 경우 결과값은 옵셔널로 반환
optionalCasted = p2 as? UniversityStudent  //Optional(Page_Contents.UniversityStudent)

// s2는 Student, a는 Person 이기 때문에 UniversityStudent로 다운 캐스팅할 수 없다
// 실패가능성을 내포하고 있기 때문에 nil이 반환될 수 있다.
optionalCasted = s2 as? UniversityStudent  //nil
optionalCasted = a as? UniversityStudent  //nil
optionalCasted = a as? Student  //nil

3-2. 강제 다운 캐스팅 - as!

  • 런타임 시점에 타입 캐스팅을 하며, 실패할 경우 런타임 오류 발생
  • 반환 타입이 옵셔널이 아니라 일반 타입이라 편하게 사용할 수 있음
optionalCasted = p2 as! UniversityStudent

//s2는 Student, a는 Person 이기 때문에 UniversityStudent가 될 수 없다.
//런타임 오류 발생
//optionalCasted = s2 as! UniversityStudent  
//optionalCasted = a as! UniversityStudent  
//optionalCasted = a as! Student

3-3. 다운캐스팅 예제

//상위 클래스
class MediaItem { 
    var name: String
    
    init(name: String) { 
        self.name = name 
    } 
} 

class Movie: MediaItem {
    var director: String
    
    init(name: String, director: String) {
        self.director = director
        super.init(name: name)
    }
}

class Song: MediaItem {
    var artist: String
    
    init(name: String, artist: String) {
        self.artist = artist
        super.init(name: name)
    }
}
let library = [ 
    Movie(name: "Casablanca", director: "Michael Curtiz"), 
    Song(name: "Blue Suede Shoes", artist: "Elvis Presley"), 
    Movie(name: "Citizen Kane", director: "Orson Welles"), 
    Song(name: "The One And Only", artist: "Chesney Hawkes"), 
    Song(name: "Never Gonna Give You Up", artist: "Rick Astley") 
]
//item을 하위 클래스로 다운캐스팅 해서 사용할 수 있다.
for item in library { 
    if let movie = item as? Movie { 
        print("Movie: \\(movie.name), dir. \\(movie.director)") 
    } else if let song = item as? Song { 
        print("Song: \\(song.name), by \\(song.artist)") 
    } 
}

//Movie: Casablanca, dir. Michael Curtiz
//Song: Blue Suede Shoes, by Elvis Presley
//Movie: Citizen Kane, dir. Orson Welles
//Song: The One And Only, by Chesney Hawkes
//Song: Never Gonna Give You Up, by Rick Astley

 

 

 

참고하였습니다. 감사합니다.

https://yagom.net/courses/swift-basic/lessons/옵셔널-심화/topic/타입캐스팅/

https://babbab2.tistory.com/127

728x90