17. 타입 캐스팅(Type Casting)

🌈 devleeky16498·2022년 4월 19일
0

타입 캐스팅은 인스턴스 타입을 확인하거나 해당 인스턴스를 자체 클래스에서 다른 상위 클래스나 하위 클래스로 취급하는 방법이다. 타입캐스팅을 사용하여 프로토콜을 준수하는지 확인도 가능하다.

타입 캐스팅을 위한 클래스 계층 정의

  1. 클래스와 하위 클래스의 계층도 타입 캐스팅을 사용해서 특정 클래스의 인스턴스 타입을 확인하고 같은 계층 내에서 다른 클래스로 인스턴스 캐스트도 가능하다.
class MediaItem {
	var name : String
    init(name : String) {
    	self.name = name
    }
}
//다음과 같은 미디어 아이템 클래스를 정의한다.

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

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

//위의 미디어 아이템을 상속하는 두개의 하위 클래스를 정의했다.

let library = [Movie(name: "Lee", director : "Micheal"), Song(name : "Park", artist : "songsong")]
//다음과 같은 라이브러리의 경우는 해당 타입을 MediaItem이라는 타입으로 유추한다.
//두 하위 클래스 타입을 포함한 배열이기 때문이다.

타입 검사

  1. 인스턴스가 특정 하위 클래스 타입인지 확인하기 위해서 타입 검사 연산자 is를 사용한다. 이 검사 연산자는 인스턴스가 하위 클래스면 true 아니면 false를 리턴한다.
var movieCount = 0
var songCount = 0

for item in library {
	if item is Movie {
    	movieCount += 1
    } else if item is Song {
    	songcount += 1
    }
}
//다음과 같이 타입을 구분해서 부울 값을 리턴해준다. 타입에 따라서 흐름제어가 가능하다.

다운 캐스팅

  1. 특정 클래스 타입의 상수 또는 변수는 하위 클래스의 인스턴스 참조가 가능하다. 이것이 가능한 경우 타입 캐스트 연산자 as? 또는 as!를 사용해서 하위 클래스 타입으로 다운 캐스트 가능하다.
  2. 다운 캐스트 성공여부에 대한 확신이 없는 경우 조건부 형식인 as?를 사용한다. 이 연산자 형식은 옵셔널을 반환하고 불가할 시 nil을 반환한다. 성공여부를 판단할때도 사용 가능하다.
  3. 다운 캐스트 성공이 확실한 경우에 한해 as!를 사용한다. 유효하지 않은 클래스 타입으로 다운캐스트 시도시 에러를 반환한다.
for item in library {
	if let movie = item as? Movie {
    	print(movie.name)
    } else if song = item as? Song {
    	print(song.name)
    }
}
//다음 코드는 위 코드에서의 라이브러리에 대한 다운캐스팅 코드이다.
//item은 현재 MediaItem의 인스턴스이기 때문에 Movie일수도, Song 일수도 있다. 따라서 옵셔널 다운캐스팅을 수행하는 것이 바람직하다.
// 위 코드는 item에 대해서 nil을 반환하지 않는 값을 받아 출력하는
// 다운캐스팅 루프구문이다. 다운캐스팅 값이 존재하면 이를 받아 출력한다.
  1. 캐스팅은 실제로 인스턴스를 수정하거나 값을 변경하지 않는다.

Any와 AnyObject에 대한 타입 캐스팅

  1. 스위프트에서는 비특정 타입 작업을 위한 2개의 특별 타입을 제공한다.
  • Any : 함수타입을 포함하여 모든 타입의 인스턴스를 나타낼 수 있다.
  • AnyObject : 모든 클래스 타입의 인스턴스를 나타낼 수 있다.
var things : [Any] = []
things.append("hi")
things.append(0.0)
things.append(42)
// 다음과 같이 모든 타입의 값을 핸들링 할 수 있다.

for thing in things {
	switch thing {
    case 0 as Int:
    	print("Int value")
    case 0 as Double:
    	print("Double value!")
    case let someString as String:
    	print(someString)
 //다음과 같이 Any에 대한 타입 캐스팅은 스위치 구문을 통해 접근한다.
 //마지막과 같이 특정 값을 명시하지 않아도, 값을 담는 상수를 통해 캐스팅이 가능하다.
 
let optionalNumber : Int? = 3
things.append(optionalNumber)
things.append(optionalNumber as Any)
//Any타입은 옵셔널 타입을 포함한다. 스위프트는 Any타입의 값이 기대되는 곳에
// 옵셔널 값을 사용하면 경고한다.
//만약 옵셔널 값을 사용하는 게 필요하다면 as연산자를 통해 Any로 명시적으로 옵셔널을 Any로 캐스트 가능하다.
profile
Welcome to Growing iOS developer's Blog! Enjoy!🔥

0개의 댓글