티스토리 뷰
안녕하세요 :) Zedd입니다.
요새 조금 바빴어요 ㅠㅠ 이것저것 하느라 글을 못썼네요!!
지금 프로토콜글은....정말 왜 이런 예제를 넣었지..?라는 의문이 드는 예제가 빡 있어서 이걸 어떻게 해야할지 모르겠어요..
프로토콜글은 조금 늦게 올라갈 것 같습니다..!!! 흐규ㅠㅠㅜㅜ
그래서 오늘은 간단하게? Type Casting(타입 캐스팅) 에 대해서 알아보려고 해요!!!!
Type Casting
타입캐스팅은 인스턴의 타입을 확인하거나, 인스턴스의 타입을 슈퍼클래스 또는 서브클래스 타입처럼 다루기 위해 사용합니다.
Swift에서 타입 캐스팅은 "is"와 "as"라는 연산자로 구현할 수 있으며, 이 두 연산자는 값의 타입을 확인하거나, 값을 다른 타입으로 변환하는 간단하고 표현적인 방법을 제공합니다.
Defining a Class Hierarchy for Type Casting
class Person {
var name: String
init(name: String) {
self.name = name
}
}
자. Person이라는 클래스를 정의해주었어요.
저장 인스턴스 프로퍼티로 name이 있네요.
초기값이 없으므로 init을 만들어준 것을 볼 수 있습니다.
var zedd = Person(name: "Zedd")
if zedd is Person{
print(true)//true
}
자!!! is를 한번 써봤어요. 완전 확 와닿죠!!
Person타입의 인스턴스인 zedd를 하나 선언하고,
이 "zedd"라는 인스턴스가 Person의 인스턴스냐? 라고 확인하는거죠.
이럴 때 is를 사용할 수 있답니다. 이렇게 인스턴스 자체를!! 확인 할 수도 있지만,
인스턴스의 프로퍼티도 당연히 확인할 수 있겠죠?
예제로 봅시다.
var zedd = Person(name: "Zedd")
if zedd.name is String{
print(true)//true
}
Person타입에는 name이라는 String타입 프로퍼티가 있었죠?
zedd.name. 즉 위에선 "Zedd"가 String타입이냐? 라고 확인하는거죠.
String타입이 맞으니 true가 나오겠네요.
어때요!!
이제 Apple예제를 봐봅시다. 이번 글 끝까지 연결되는 예제들이니 잘 보셔야해요.
class MediaItem {
var name: String
init(name: String) {
self.name = name
}
}
이렇게 MediaItem이라는 클래스를 정의했네요.. Person과 똑같죠..?ㅎㅎ
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)
}
}
그리고 MediaItem을 상속받는!!!! 즉 MediaItem을 슈퍼클래스로 하는 Movie클래스와 Song클래스를 정의했어요.
let library = [
Movie(name: "죽은 시인의 사회", director: "피터 위어"),
Song(name: "창공", artist: "김준석"),
Movie(name: "인터스텔라", director: "크리스토퍼 놀란"),
Movie(name: "공범자들", director: "최승호")
]
그리고 배열하나를 만듭니다. 이 안에는 방금 만든! MediaItem을 상속받는 Movie와 Song타입 인스턴스들을 넣어줍니다.
자연스럽게 library라는 배열은 MediaItem타입의 배열이 되게됩니다.
자, 위에서 해본 "is"를 사용해볼까요?
var movieCount = 0
var songCount = 0
for item in library {
if item is Movie {
movieCount += 1
} else if item is Song {
songCount += 1
}
}
print("Media library는 \(movieCount)개의 영화와 \(songCount)개의 노래가 있어요!")
길어보이지만 전혀!! 어렵지 않습니다. 저~~기 위에서 했던 예제랑 똑같아요.
library배열을 돌면서 해당 인스턴스가 Movie타입인지, Song타입인지 "is" 로 확인하고 있죠?
출력은?
Media library는 3개의 영화와 1개의 노래가 있어요!
가 나오겠네요. ㅎㅎ
Downcasting
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: 죽은 시인의 사회, dir. 피터 위어
Song: 창공, by 김준석
Movie: 인터스텔라, dir. 크리스토퍼 놀란
Movie: 공범자들, dir. 최승호
*/
if let구문을 활용한 것을 볼 수 있네요. 그리고 as? 라는 조건부 형식 다운캐스팅을 진행하고 있네요.
왜냐하면 library는 MediaItem타입 배열이고, 그 안에 들어있는 인스턴스는 MediaItem의 서브클래스들인 Movie와 Song이니까요.
역시 for문을 돌면서, 해당 인스턴스가 Movie로 다운캐스팅 될 수 있으면!!! print구문을 실행하네요.
해당 영화의 이름과 감독이름을 출력하도록요.
그리고 만약 해당 인스턴스가 Song타입으로 다운캐스팅 할 수 있으면 해당 노래의 이름과 아티스트 이름을 출력하네요.
위 예제를 어렵게 생각하지마세요! MediaItem이 슈퍼클래스였고, 지금 Movie와 Song클래스는 MediaItem의 서브클래스(자식클래스)이므로, 다운캐스팅이 가능한 건 당연하겠죠? 그걸 as로 해주는거에요!!
item은 MediaItem인스턴스 이기때문에, Movie일수도 있고, Song일 수도 있는것이죠.
그리고 as? 는 옵셔널 값을 반환하기 때문에, if let구문으로 값을 꺼내온 것을 볼 수 있습니다.
그 꺼내온 값을 Movie타입으로 다운캐스팅할 수 있으면 movie에 넣고, Song타입으로 다운캐스팅 할 수 있으면 song에 넣는거죠.
Type Casting for Any and AnyObject
var things = [Any]()
things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append((3.0, 5.0))
things.append(Movie(name: "대장 김창수", director: "이원태"))
things.append({ (name: String) -> String in "Hello, \(name)" })
Any는 모든 타입을 넣을 수 있다고 그랬죠? Int부터 클로져까지!!!!!넣을 수 있답니다. 와 클로져를 넣을 수 있다는것은 지금알았네요 ㄷㄷ
정리하면, things배열은 Any타입으로, 두개의 Int값, 두개의 Double값, String값, (Double, Double)인 튜플, 위에서 정의한 Movie타입, 그리고 문자열을 반환하는 클로져가 들어가있습니다.
이제 "as"를 써볼건데요, 문서에는 as에 대한 언급이 없네요.. as?와 as!만 있고..
as와 as? as! 의 차이점은 실행되는 시간의 차이가 있다네요.
as는 컴파일타임에, as?와 as!는 런타임에 실행된다고 합니다.
그리고, 업캐스팅과 패턴매칭(switch)에서만 사용할 수 있다고해요. 바로 예제처럼요!
for thing in things {
switch thing {
case 0 as Int:
print("Int타입 0")
case 0 as Double:
print("Double 타입 0")
case let someInt as Int:
print("0이 아닌 Int \(someInt)")
case let someDouble as Double where someDouble > 0:
print("양의 Double타입 \(someDouble)")
case is Double:
print("다른 Double들은 출력하고 싶지 않네,,")
case let someString as String:
print("String값은 \"\(someString)\"")
case let (x, y) as (Double, Double):
print("x와 y좌표는 \(x), \(y)")
case let movie as Movie:
print("영화 이름은 \(movie.name), dir. \(movie.director)")
case let stringConverter as (String) -> String:
print(stringConverter("미카엘"))
default:
print("다른거~~")
}
}
자, 이렇게 오늘은 타입캐스팅에 대해서 알아봤어요 :)
도움이 되었으면 좋겠네요!!! 얼른 프로토콜 글도 쓰도록 할게요 XD..
안녕!!
'Swift' 카테고리의 다른 글
Swift) dynamic이란? / Realm의 dynamic var는? (8) | 2017.11.17 |
---|---|
Swift ) Patterns (0) | 2017.10.31 |
Swift ) Protocols (2) (3) | 2017.10.18 |
Swift ) Method (7) | 2017.10.17 |
Swift ) Protocols (1) (4) | 2017.10.16 |
- swift array
- Xcode
- WidgetKit
- Accessibility
- 스위프트 문법
- swift tutorial
- np-hard
- SwiftUI
- github
- fastlane
- 피아노
- UIBezierPath
- swift 공부
- swift3
- swift delegate
- IOS
- actor
- Git
- 제이슨 파싱
- swift sort
- iOS delegate
- WKWebView
- WWDC
- ios 13
- np-complete
- Swift
- 회고
- 스위프트
- FLUTTER
- Combine
- Total
- Today
- Yesterday