728x90
반응형

스위프트의 타입캐스팅

타입 캐스팅은 인스턴스의 타입을 확인하는 용도 이다.
클래스의 인스턴스를 부모 혹은 자식 클래스의 타입으로 사용할 수 있는지 확인하는 용도
is , as 연산자를 사용한다.

정리해서,
인스턴스의 타입을 확인하거나 인스턴스 타입의 슈퍼클래스 또는 서브클래스 타입처럼 다루기 위해 사용!

다음 클래스를 통해 예를 들어서 확인해보려고 한다.

class Person {
    var name: String = ""
    func breath() {
        print("하트 비트")
    }
}

// Person 클래스 상속
class Student: Person {
    var school: String = ""
    func goToSchool() {
        print("학교 가자")
    }
}

// Student 클래스 상속
class UniversityStudent: Student {
    var major: String = ""
    func goToMT() {
        print("엠티 궈궈~")
    }
}

Person 클래스 생성
Person 클래스를 상속받은 Student 클래스 생성
Student 클래스를 상속받은 UniversityStudent 클래스 생성

그리고 각 클래스의 인스턴스를 생성했다.

// 각 클래스 인스턴스 생성
var jak: Person = Person()
var joe: Student = Student()
var jin: UniversityStudent = UniversityStudent()

 

타입 확인  (is)

is 를 사용해서 타입을 확인할 수 있다.

// 타입 확인 is 사용
var result: Bool

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

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

result = jin is Person // true
result = jin is Student // true
result = jin is UniversityStudent // true

위의 예를 확인해보면
jak 는 Person 클래스의 인스턴스이므로 Person 클래스 타입일 때 true 를 반환한다.
Joe 는 Person -> Student 클래스의 인스턴스이므로 Person 과 Student 클래스 타입일 때 true 를 반환
jin 은 Person -> Student -> UniversityStudent 클래스의 인스턴스 이므로 3개의 클래스 타입에서 true 를 반환하는 것을 확인할 수 있다.

그리고 if 와 switch 에서도 활용해서 사용해볼 수 있다.

// 조건문을 통해서 사용할 수 있다.
// jak 는 Person 클래스 인스턴스
if jak is UniversityStudent {
    print("나 대학생!")
} else if jak is Student {
    print("나 학생!")
} else if jak is Person {
    print("나 사람?!")
}

// switch 문에서도 사용할 수 있다.
// jak 는 Person 클래스 인스턴스
switch jak{
case is Person:
    print("사람입니다.")
case is Student:
    print("학생입니다.")
case is UniversityStudent:
    print("대학생입니다.")
default:
    print("아무도 아니야~")
}

// jin 은 University 클래스 인스턴스
switch jin{
case is UniversityStudent:
    print("대학생입니다.")
case is Student:
    print("학생입니다.")
case is Person:
    print("사람입니다.")
default:
    print("아무도 아니야~")
}


========== 출력 결과 =========
나 사람?!
사람입니다.

 

그리고 업 캐스팅과 다운 캐스팅을 통해서 부모 혹은 자식 클래스의 인스턴스로 사용할 수 있도록 타입 정보를 전환해준다.

업 캐스팅 (Up Casting)

as를 사용하여 부모 클래스의 인스턴스로 사용할 수 있도록 해준다.
Any 혹은 AnyObject 로도 타입 정보를 변환할 수 있다.
암시적으로 처리되므로 꼭 필요한 경우가 아니라면 생략해도 무방하다.

// 업 캐스팅
// 부모 클래스의 인스턴스로 사용할 수 있게 해준다.
// 잘 사용하지는 않는다.
var vein: Person = UniversityStudent() as Person
var kaisa: Student = Student()
var caytlin: Any = Person() // as Any 생략 가능

vein 는 UniversityStudent 클래스의 인스턴스를 생성하고 Person 클래스를 사용할 수 있도록 업 캐스팅을 해주었다.
caytlin 은 Person 인스턴스를 생성해서 Any 클래스를 사용할 수 있도록 업 캐스팅 해주었다.
여기서 as Any 는 생략할 수 있다.

다운 캐스팅 (down casting)

as? 또는 as! 를 사용해서 자식 클래스의 인스턴스로 사용할 수 있도록 컴파일러에게 인스턴스의 타입 정보를 전환해준다.

조건부 다운 캐스팅 (as?)

as?  사용
캐스팅에 실패하면, 캐스팅하려는 타입에 부합하지 않는 인스턴스라면 nil 을 반환하기 때문에
결과의 타입은 옵셔널 타입이다.

var vein: Person = UniversityStudent() as Person
var kaisa: Student = Student()
var caytlin: Any = Person() // as Any 생략 가능

// 조건부 다운 캐스팅
// as?
var optionalCasted: Student?

// vein 은 UniversityStudent 클래스 인스턴스
optionalCasted = vein as? UniversityStudent

// kaisa 는 Student 클래스 인스턴스
optionalCasted = kaisa as? UniversityStudent // nil

// caytlin 은 Person 인스턴스
optionalCasted = caytlin as? UniversityStudent // nil
optionalCasted = caytlin as? Student // nil

optionalCasted 는 Student 클래스 옵셔널 타입이다.
optionalCaseted 에 UniversityStudent 클래스의 인스턴스인vein 을 입력받아
UniversityStudent 클래스를 사용할 수 있도록 다운캐스팅 해주었다.
kaisa 는 Student 클래스의 인스턴스이므로 UniversityStudent 클래스로 다운 캐스팅할 수 없기 때문에 nil 을 반환한다.
caytlin 도 마찬가지로 Person 클래스의 인스턴스이므로 다운 캐스팅이 되지 않아 nil 을 반환하는 것을 확인할 수 있다.

강제 다운 캐스팅

as!  사용
캐스팅에 실패하면, 캐스팅하려는 타입에 부합하지 않는 인스턴스라면 런타임 오류가 발생한다.
조건부 다운 캐스팅의 경우에는 nil 을 반환했다.
캐스팅에 성공하면 옵셔널이 아닌 일반 타입을 반환한다.

var vein: Person = UniversityStudent() as Person
var kaisa: Student = Student()
var caytlin: Any = Person() // as Any 생략 가능

// 강제 다운 캐스팅
// as!

var forcedCaseted: Student

forcedCaseted = vein as! UniversityStudent
// 런타임 에러 발생
// forcedCaseted = kaisa as! UniversityStudent
// forcedCaseted = caytlin as! UniversityStudent
// forcedCaseted = caytlin as! Student

vein 은 UniversityStudent 클래스의 인스턴스이므로 다운 캐스팅이 되는 것을 확인할 수 있고
나머지의 경우 다운 캐스팅이 되지 않기 때문에 런타임 오류가 발생한다.

추가적으로 타입 캐스팅을 다양하게 활용해볼 수 있다.

func doSomethingWithSwitch(someone: Person) {
    switch someone {
    case is UniversityStudent:
        (someone as! UniversityStudent).goToMT()
    case is Student:
        (someone as! Student).goToSchool()
    case is Person:
        (someone as! Person).breath()
    }
}

doSomethingWithSwitch(someone: vein as Person)
doSomethingWithSwitch(someone: vein)
doSomethingWithSwitch(someone: kaisa)
doSomethingWithSwitch(someone: jak)

========== 출력 결과 =========
엠티 궈궈~
엠티 궈궈~
학교 가자
하트 비트

func doSomething(someone: Person) {
    if let universityStudent = someone as? UniversityStudent {
        universityStudent.goToMT()
    } else if let student = someone as? Student {
        student.goToSchool()
    } else if let person = someone as? Person {
        person.breath()
    }
}


doSomething(someone: vein as Person)
doSomething(someone: vein)
doSomething(someone: kaisa)
doSomething(someone: jak)

========== 출력 결과 ==========
엠티 궈궈~
엠티 궈궈~
학교 가자
하트 비트

 

 

- 참고 사이트 - 

www.edwith.org/boostcamp_ios/lecture/11312

 

[LECTURE] 24. 타입 캐스팅 (💎생각해보기) : edwith

생각해보기   ▶as 연산자는 실제로 대상 객체의 타입을 변경하는 것일까요?   강의내용 - 부스트코스

www.edwith.org

minsone.github.io/mac/ios/swift-type-casting-summary

 

[Swift]Type Casting 정리

형 변환(Type Casting) 형 변환은 인스턴스의 타입을 검사하는 방법으로, 인스턴스를 클래스 계층에서의 슈퍼클래스나 서브클래스를 다룬다. Swift에 형 변환은 is와 as 연산자로 구현되며, 이들 연산

minsone.github.io

zeddios.tistory.com/265

 

Swift ) Type Casting

안녕하세요 :) Zedd입니다. 요새 조금 바빴어요 ㅠㅠ 이것저것 하느라 글을 못썼네요!! 지금 프로토콜글은....정말 왜 이런 예제를 넣었지..?라는 의문이 드는 예제가 빡 있어서 이걸 어떻게 해야할

zeddios.tistory.com

 

728x90
반응형
복사했습니다!