타입 캐스팅 TypeCasting

이유진·2024년 3월 12일
0

Swift 문법

목록 보기
7/9

타입 캐스팅?

  • 변수나 객체의 타입을 다른 타입으로 변환하는 프로세스
  • is
    • 연산자 타입 체크
    • 비교 결과 bool 타입으로 반환(true/false)
      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
  • as, as?, as!
    • 복습
      • 타입?
        • 기본 데이터 타입: Int, Double, Bool, String 등
        • 옵셔널 Optional
        • 커스텀 데이터 타입: struct, class, enum, protocol 등
    • 상속
      • 클래스의 상속에 대해 알고 있어야 타입 캐스팅을 이해할 수 있다.
    • as : 업캐스팅, 자식 타입으로 지정되어 있는 것을 부모 타입으로 끌어올린다.
      class Person {
          var id = 0
          var name = "name"
          var email = "hgk@gmail.com"
      }
      
      class Worker: Person {
          // id
          // name
          // email
          var salary = 300
      }
      
      class Programmer: Worker {
          // id
          // name
          // email
          // salary
          var lang = "Swift"
      }
      
      // 업캐스팅 - as
      let person = Person()
      let worker = Worker()
      let programmer1 = Programmer()
      
      let personList = [person, worker, programmer1]
      personList[1].name
      //업 캐스팅
      //배열의 타입을 명시하지 않으면 Swift는 배열의 요소를 가장 큰 공통의 타입으로 추론한다.
      //Person 클래스가 가장 상위 클래스이기 때문에 배열의 요소를 Person 클래스로 추론한다.
      //personList[1].salary // Person 타입으로 보고 있기 때문에 salary에 접근하지 못함
    • as? : 다운캐스팅, 부모 타입으로 지정되어 있는 것을 자식 타입으로 내린다. 성공 시 옵셔널 타입의 인스턴스 반환, 실패하면 nil 반환
      class Person {
          var id = 0
          var name = "name"
          var email = "hgk@gmail.com"
      }
      
      class Worker: Person {
          // id
          // name
          // email
          var salary = 300
      }
      
      class Programmer: Worker {
          // id
          // name
          // email
          // salary
          var lang = "Swift"
          
      let person = Person()
      let worker = Worker()
      let programmer1 = Programmer()
      
      //다운 캐스팅1
      let pro = programmer as? Programmer
          pro?.lang
      
      if let person2 = programmer as? Programmer {
          person2.lang
      }
      //같은 클래스의 인스턴스끼리는 같은 클래스로 다운캐스팅 가능
      //progammer1은 Programmer 클래스 인스턴스이기 때문에 Programmer 클래스로 다운 캐스팅 가능
      //그리고 이 경우는 "항상 성공"
      //let: 다운 캐스팅 시도 -> 결과를 옵셔널 값으로 처리
      //if let: 다운 캐스팅 시도 -> 성공 시에만 코드 처리
      
      //다운 캐스팅2
      if let person3 = worker as? Programmer {
          print("다운캐스팅 성공")
      } else {
          print("다운캐스팅 실패")
      }
      //출력 "다운캐스팅 실패"
      //다운 캐스팅이 되지 않는 이유?
      //Programmer 클래스의 인스턴스가 Worker 클래스의 "모든 속성과 메서드"를 상속 받은 것은 맞지만,
      //Worker 클래스의 인스턴스가 Programmer 클래스의 인스턴스가 되는 것은 아니다.
      //클래스의 속성과 메서드를 상속 받는 것과, 인스턴스는 별개의 개념
      //다운 캐스팅2가 성공하려면?
      if let person3 = worker as? Programmer {
          print("다운캐스팅 성공")
      } else {
          print("다운캐스팅 실패")
      }
      //출력 "다운캐스팅 성공"
      
      //실행은 되는데 이런 주의문이 뜬다.
      //항상 성공하는 캐스팅이라고 안내해준다.
      //왜일까? 밑에 이어서 설명!
      Conditional cast from 'Programmer' to 'Programmer' always succeeds
      //1
      let person = Person()
      let worker = Worker()
      let programmer1 = Programmer()
      
      if let person3 = programmer as? Programmer {
          print("다운캐스팅 성공")
      } else {
          print("다운캐스팅 실패")
      }
      
      /*
      1에서는 programmer1에 타입을 따로 지정해주지 않았다.
      따라서 programmer1의 타입은 타입 추론에 의해 "Programmer 타입"으로 지정이 된다.
      if let에서 사용된 programmer1의 타입과 Programmer의 타입이 동일하기 때문에
      항상 성공할 수 밖에 없는 캐스팅이라고 안내해준 것이다!
      */
      
      //그렇다면 이러한 안내창이 뜨지 않는 경우는 뭘까?
      //2에서 살펴보자
      
      //2
      let person: Person = Worker()        
      let worker: Person = Worker()
      let programmer: Worker = Programmer()
      
      if let person3 = programmer as? Programmer {
          print("다운캐스팅 성공")
      } else {
          print("다운캐스팅 실패")
      }
      
      /*
      2에서는 programmer의 타입을 Worker로 지정해주었다. (Type Annotation)
      따라서 if let에서 사용된 programmer의 타입과 Programmer의 타입(Programmer)이 동일하지 않기 때문에
      1에서 떴던 경고창이 뜨지 않는다!
      */
    • as! : 다운캐스팅, 부모 타입으로 지정되어 있는 것을 자식 타입으로 내린다. 강제 타입 캐스팅, 성공하면 인스턴스 반환, 실패하면 런타임 에러
      let pro2 = worker2 as! Programmer // Error : 타입 변환 실패시 오류

2개의 댓글

comment-user-thumbnail
2024년 3월 12일

이야기 나눴던 내용 잘 정리해주셔서 다시 한 번 복습했어요 감사해용!

답글 달기
comment-user-thumbnail
2024년 3월 12일

저도 다시 정리해볼게요 감사합니다 !

답글 달기