ν‹°μŠ€ν† λ¦¬ λ·°

Swiftμ—μ„œ νƒ€μž…μ€ 맀우 μ€‘μš”ν•œ κ°œλ…μž…λ‹ˆλ‹€. νƒ€μž…μ€ 데이터λ₯Ό ν•΄μ„ν•˜λŠ” 방법을 μ •μ˜ν•˜κ³ , λ™μΌν•œ 데이터라도 νƒ€μž…μ— 따라 μ „ν˜€ λ‹€λ₯Έ μ˜λ―Έμ™€ κΈ°λŠ₯을 κ°€μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ νƒ€μž…μ„ λ‹€λ£° 수 있게 ν•΄μ£ΌλŠ” 것이 λ°”λ‘œ νƒ€μž… μΊμŠ€νŒ…μž…λ‹ˆλ‹€.

 

νƒ€μž… μΊμŠ€νŒ…μ΄λž€?

νƒ€μž… μΊμŠ€νŒ…μ€ νƒ€μž…μ„ λ³€κ²½ν•˜μ—¬ 데이터λ₯Ό λ‹€λ₯Έ λ°©μ‹μœΌλ‘œ ν•΄μ„ν•˜λŠ” λ°©λ²•μœΌλ‘œ, μΈμŠ€ν„΄μŠ€μ˜ νƒ€μž…μ„ ν™•μΈν•˜κ±°λ‚˜ 클래슀 계측 ꡬ쑰 λ‚΄μ—μ„œ νƒ€μž…μ„ μ „ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Swiftμ—μ„œλŠ” 주둜 두 가지 μ£Όμš” μž‘μ—…μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€:

 

1. μΈμŠ€ν„΄μŠ€μ˜ νƒ€μž…μ„ 확인

2. 클래슀 계측 ꡬ쑰 λ‚΄μ—μ„œ μΈμŠ€ν„΄μŠ€λ₯Ό λ‹€λ₯Έ μƒμœ„ ν΄λž˜μŠ€λ‚˜ ν•˜μœ„ 클래슀둜 λ³€ν™˜

 

λ˜ν•œ, νƒ€μž…μ΄ νŠΉμ • ν”„λ‘œν† μ½œμ„ μ€€μˆ˜ν•˜λŠ”μ§€ 여뢀도 νƒ€μž… μΊμŠ€νŒ…μ„ 톡해 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

νƒ€μž… μΊμŠ€νŒ…μ˜ κ΅¬ν˜„

Swiftμ—μ„œλŠ” is μ—°μ‚°μžμ™€ as μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜μ—¬ νƒ€μž… μΊμŠ€νŒ…μ„ κ΅¬ν˜„ν•©λ‹ˆλ‹€.

예제λ₯Ό 톡해 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

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")
]  // library의 νƒ€μž…μ€ [MediaItem]으둜 μΆ”λ‘ λœλ‹€.
// Moview와 Song νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€κ°€ MediaItem으둜 μ—…μΊμŠ€νŒ…λœ 것

 

 

1. is μ—°μ‚°μž

 

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
    }
}

print("Media library contains \(movieCount) movies and \(songCount) songs")
// Prints "Media library contains 2 movies and 3 songs"

 

 

2. as μ—°μ‚°μž

 

as μ—°μ‚°μžλŠ” νƒ€μž… μΊμŠ€νŒ…μ„ μˆ˜ν–‰ν•˜λŠ” 데 μ‚¬μš©λ©λ‹ˆλ‹€.

계측 관계가 μžˆλŠ” νƒ€μž… κ°„μ—λ§Œ μ‚¬μš© κ°€λŠ₯ν•˜λ©°, 계측 관계가 μ—†λŠ” νƒ€μž… κ°„μ—λŠ” μΊμŠ€νŒ…μ΄ μ‹€νŒ¨ν•©λ‹ˆλ‹€.

 

μ—…μΊμŠ€νŒ… (Upcasting)

 

μ—…μΊμŠ€νŒ…μ€ μ„œλΈŒ 클래슀 μΈμŠ€ν„΄μŠ€λ₯Ό 슈퍼 클래슀 νƒ€μž…μœΌλ‘œ μΊμŠ€νŒ…ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

μ—…μΊμŠ€νŒ…μ€ 항상 μ„±κ³΅ν•˜λ©°, 컴파일 μ‹œμ μ— μΊμŠ€νŒ… κ°€λŠ₯ μ—¬λΆ€κ°€ κ²°μ •λ©λ‹ˆλ‹€.

 

μœ„μ˜ μ˜ˆμ œμ—μ„œ library의 νƒ€μž…μ€ [MediaItem]으둜 μΆ”λ‘ λ©λ‹ˆλ‹€. μ΄λŠ” Movie와 Song νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€κ°€ MediaItem으둜 μ—…μΊμŠ€νŒ…λœ κ²ƒμž…λ‹ˆλ‹€.

 

μ—…μΊμŠ€νŒ…μ„ ν•˜λŠ” 방식은 μœ„μ—μ„œ λ³Έ library처럼 νƒ€μž… 좔둠을 μ΄μš©ν•΄λ„ 되고 직접 νƒ€μž…μ„ λͺ…μ‹œν•΄λ„ λ©λ‹ˆλ‹€.

λ˜ν•œ as μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜μ—¬ 직접 μ—…μΊμŠ€νŒ…μ„ ν•΄μ£Όλ©΄ λ©λ‹ˆλ‹€.

// 직접 μ—…μΊμŠ€νŒ…
let mediaItem1 = Movie(name: "Casablanca", director: "Michael Curtiz") as MediaItem

// νƒ€μž… λͺ…μ‹œ
let mediaItem2: MediaItem = Movie(name: "Casablanca", director: "Michael Curtiz")

 

μΆ”κ°€λ‘œ, Swift의 κΈ°λ³Ένƒ€μž…λ“€μ„ 그에 λŒ€μ‘ν•˜λŠ” Foundation 클래슀 νƒ€μž…μœΌλ‘œ λ³€ν™˜ν•˜λŠ” λΈŒλ¦Ώμ§•(Bridging)을 μ˜λ―Έν•˜κΈ°λ„ ν•©λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, String νƒ€μž…μ„ NSString νƒ€μž…μœΌλ‘œ μ—…μΊμŠ€νŒ…ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

 

λ‹€μš΄μΊμŠ€νŒ… (DownCasting)

 

λ‹€μš΄μΊμŠ€νŒ…μ€ 슈퍼 클래슀 μΈμŠ€ν„΄μŠ€λ₯Ό μ„œλΈŒ 클래슀 νƒ€μž…μœΌλ‘œ μΊμŠ€νŒ…ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

컴파일 μ‹œμ μ— 성곡 μ—¬λΆ€λ₯Ό μ•Œ 수 μ—†μœΌλ©°, λŸ°νƒ€μž„μ— 체크가 μ΄λ£¨μ–΄μ§‘λ‹ˆλ‹€.

 

λ‹€μš΄μΊμŠ€νŒ…μ€ μ‹€νŒ¨ν•  수 있기 λ•Œλ¬Έμ—, as?λ₯Ό μ‚¬μš©ν•˜μ—¬ μ˜΅μ…”λ„μ„ λ¦¬ν„΄ν•˜κ±°λ‚˜ as!λ₯Ό μ‚¬μš©ν•˜μ—¬ κ°•μ œ μΊμŠ€νŒ…μ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ, μ „ν˜€ λ¬΄κ΄€ν•œ νƒ€μž…μœΌλ‘œμ˜ μΊμŠ€νŒ…μ€ μ»΄νŒŒμΌλŸ¬κ°€ κ²½κ³ λ₯Ό 주기도 ν•©λ‹ˆλ‹€.

MediaItem νƒ€μž…μ„ μ „ν˜€ λ¬΄κ΄€ν•œ String νƒ€μž…μœΌλ‘œ μΊμŠ€νŒ…ν•˜λ €κ³  ν•˜λ©΄ κ²½κ³ λ₯Ό μ€€λ‹€.

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

 

νƒ€μž… μΊμŠ€νŒ…μ€ μ‹€μ œλ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό μˆ˜μ •ν•˜κ±°λ‚˜ 값을 λ³€κ²½ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

κΈ°λ³Έ μΈμŠ€ν„΄μŠ€λŠ” λ™μΌν•˜κ²Œ μœ μ§€λ˜λ©°, λ‹¨μˆœνžˆ 캐슀트된 νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λ‘œ 처리되고 μ ‘κ·Όλ©λ‹ˆλ‹€.

 

μ•„λž˜ 이미지와 같이 library λ°°μ—΄μ˜ 첫 번째 μš”μ†ŒλŠ” μ΄ˆκΈ°μ— Movie νƒ€μž…μœΌλ‘œ μ΄ˆκΈ°ν™”κ°€ λ˜μ§€λ§Œ,

MediaItem νƒ€μž…μœΌλ‘œ μ—…μΊμŠ€νŒ… λ˜μ–΄ director ν”„λ‘œνΌν‹°μ—λŠ” μ ‘κ·Όν•  수 μ—†μŠ΅λ‹ˆλ‹€.

print(library[0].director)

Movie ν΄λž˜μŠ€μ— μ„ μ–Έλœ director λ³€μˆ˜μ—λŠ” 접근을 ν•˜μ§€ λͺ»ν•œλ‹€.

 

λ²”μš© νƒ€μž… (Any, AnyObject)

νƒ€μž… μΊμŠ€νŒ…μ„ μˆ˜ν–‰ν•  λ•Œ 일반적으둜 상속 관계에 μžˆλŠ” 클래슀끼리만 μΊμŠ€νŒ…μ΄ κ°€λŠ₯ν•˜μ§€λ§Œ, Any와 AnyObject νƒ€μž…μ„ μ‚¬μš©ν•  경우 상속 관계에 μžˆμ§€ μ•Šμ•„λ„ νƒ€μž… μΊμŠ€νŒ…μ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

Any: λͺ¨λ“  νƒ€μž…μ„ λ‚˜νƒ€λƒ…λ‹ˆλ‹€. (κ°’ νƒ€μž…, μ°Έμ‘° νƒ€μž…, ν•¨μˆ˜ νƒ€μž… λ“±)

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: "Ghostbusters", director: "Ivan Reitman"))
things.append({ (name: String) -> String in "Hello, \(name)" })

 

AnyObject: λͺ¨λ“  μ°Έμ‘° νƒ€μž… (클래슀)을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€. μ°Έμ‘° νƒ€μž…μ΄ μ•„λ‹Œ 것을 μ‚¬μš©ν•˜λ©΄ μ•„λž˜μ™€ 같이 μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€.

var things: [AnyObject] = []
 
things.append(1)
things.append(1.0)
things.append("Horang")
things.append(false)
things.append(print("Horang is smart"))

 

Any둜 μ„ μ–Έλœ μš”μ†Œλ“€μ„ μ‚¬μš©ν•  λ•ŒλŠ” Switchλ¬Έ (νŒ¨ν„΄ 맀칭)κ³Ό is, as ꡬ문을 μ‘°ν•©ν•˜μ—¬ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.

for thing in things {
    switch thing {
    case 0 as Int:
        print("zero as an Int")
    case 0 as Double:
        print("zero as a Double")
    case let someInt as Int:
        print("an integer value of \(someInt)")
    case let someDouble as Double where someDouble > 0:
        print("a positive double value of \(someDouble)")
    case is Double:
        print("some other double value that I don't want to print")
    case let someString as String:
        print("a string value of \"\(someString)\"")
    case let (x, y) as (Double, Double):
        print("an (x, y) point at \(x), \(y)")
    case let movie as Movie:
        print("a movie called \(movie.name), dir. \(movie.director)")
    case let stringConverter as (String) -> String:
        print(stringConverter("Michael"))
    default:
        print("something else")
    }
}


// zero as an Int
// zero as a Double
// an integer value of 42
// a positive double value of 3.14159
// a string value of "hello"
// an (x, y) point at 3.0, 5.0
// a movie called Ghostbusters, dir. Ivan Reitman
// Hello, Michael

 

Any νƒ€μž…μ€ μ˜΅μ…”λ„ νƒ€μž…μ„ ν¬ν•¨ν•˜μ—¬ λͺ¨λ“  νƒ€μž…μ˜ 값을 λ‚˜νƒ€λ‚Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

Any νƒ€μž…μ΄ κΈ°λŒ€λ˜λŠ” 곳에 μ˜΅μ…”λ„ 값을 μ‚¬μš©ν•˜λ©΄ κ²½κ³ κ°€ λ°œμƒν•©λ‹ˆλ‹€. 이 경우, as μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜μ—¬ Any νƒ€μž…μœΌλ‘œ μΊμŠ€νŒ…ν•΄μ£Όμ–΄μ•Ό ν•©λ‹ˆλ‹€.

let optionalNumber: Int? = 3
things.append(optionalNumber)        // Warning
things.append(optionalNumber as Any) // No warning

 

Any와 AnyObjectλŠ” λͺ¨λ“  νƒ€μž…μ„ 담을 수 μžˆμ§€λ§Œ, λŸ°νƒ€μž„ μ‹œμ μ— νƒ€μž…μ΄ κ²°μ •λ˜κΈ° λ•Œλ¬Έμ— 였λ₯˜κ°€ λ°œμƒν•˜λ©΄ λŸ°νƒ€μž„ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€.

λ˜ν•œ, μ‚¬μš©ν•  λ•ŒλŠ” μ‹€μ œ νƒ€μž…μœΌλ‘œ λ‹€μš΄μΊμŠ€νŒ…μ΄ 거의 ν•„μˆ˜μ μ΄κΈ° λ•Œλ¬Έμ— λŸ°νƒ€μž„ μ„±λŠ₯에 쒋지 λͺ»ν•œ 영ν–₯을 μ£Όκ³ , μ„€κ³„μƒμœΌλ‘œλ„ λ°”λžŒμ§ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ, κ°€λŠ₯ν•˜λ©΄ ꡬ체적인 νƒ€μž…μ„ μ‚¬μš©ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

 

참고 🐯

Documentation

Swift의 νƒ€μž… μΊμŠ€νŒ…

Swift) is, as - νƒ€μž… μΊμŠ€νŒ… (Type Casting)

Swift) Any와 AnyObject μ•Œμ•„λ³΄κΈ°