아삭아삭 iOS 개발

Any와 AnyObject에 대해 설명하시오 본문

면접대비

Any와 AnyObject에 대해 설명하시오

바닐라머스크 2022. 10. 30. 23:55

(본 게시물은 개인 공부 기록용이므로 내용에 오류가 있을 수 있습니다.)

 

Swift는 특정하지 않은 타입들의 작용을 위해 Any와 AnyObject라는 두 가지 특별한 타입을 제공하고 있습니다.

아래에서 해당 타입들의 공통점과 차이점에 대해 알아보고 샘플 코드까지 살펴보겠습니다~

 

■ Any vs. AnyObject 공통점

  • 둘 다 여러 타입에 대응이 가능함
  • 둘 다 컴파일 시점에는 어떤 타입으로 된 요소를 갖고 있는지 알 수 없으며, 런타임 시점에 타입이 결정
    → 그래서 TypeCasting 하지 않으면 각 멤버에 대한 접근도 불가능함
📌 NOTE
실제 코딩시에는 Any 타입의 사용을 최대한 지양하는 것이 좋음.
왜냐하면 런타임 시점에야 타입이 결정되기 때문에 런타임 오류가 발생할 수 있기 때문에 주의가 필요함.

 

■ Any vs. AnyObject 차이점

Any

    • 구조체, 열거형, 클래스, 클로저 등 모든 타입에 대한 인스턴스 담기 가능
      (그래도 실제 코딩시에는 Any 타입사용을 최대한 지양하는 것이 좋음..!)
📌 NOTE
Any타입은 옵셔널 타입을 포함한 타입 또한 나타낼 수 있다.
그래서 swift는 너가 사용하는 옵셔널값의 타입이 Any일 것 같으면 아래 예시처럼 경고를 보낸다.
만약 너가 Any타입으로 옵셔널 값을 사용해야만 한다면, 옵셔널을 Any로 명확하게 cast하기 위해 as 오퍼레이터를 사용할 수 있다.

<그림1. as를 사용하여 Any로 캐스팅함>

 

AnyObject

  • 모든 클래스 타입의 인스턴스만 담기 가능 가능
    - 아래 <그림2>에서의 AnyObject 정의를 보면 classes 라고 한정하여 명시하고 있다.
    ex) 아래 <그림3>을 보면 anythingList 상수의 타입은 AnyObject 배열이다.
    해당 배열에 들어가는 세 가지 요소들인 artistName, isAlbumGood, tracks가 클래스 타입의 인스턴스가 아니기 때문에 오류가 나고 있다.
  • 클래스 제약 설정 가능
    • 프로토콜에 대해 클래스의 인스턴스 타입에만 들어가도록 제약을 주고 싶을때,
      프로토콜 선언시 타입을 AnyObject로 주기도 함
protocol customProtocol: AnyObject {
}

 

<그림2. AnyObject의 공식문서 내용>

 

<그림3. AnyObject 타입의 배열을 나타내는 상수 anythingList>

 

 

■ Any 예시

아래 예시에서 everything 배열은 Int, Double, String, (Double, Double)의 tuple, Album타입인 "pH-1", String값을 받아서 또 다른 String값을 리턴하는 Closure 등을 포함하고 있다.

 

// 공식문서 예시 참고하여 새로 작성함

import Foundation

class Music {
    var artist: String
    init(artist: String) {
        self.artist = artist
    }
}

class Album: Music {
    var genre: String
    init(artist: String, genre: String) {
        self.genre = genre
        super.init(artist: artist)
    }
}

var everything: [Any] = []

everything.append(5)
everything.append(9.9)
everything.append(26)
everything.append(3.14159)
everything.append("hoi")
everything.append((1.0, 2.0))
everything.append(Album(artist: "pH-1", genre: "hip-hop"))
everything.append({ (artist: String) -> String in "Hey, \(artist)" })

 

Any나 AnyObject 타입이라고만 알려진 변수나 상수의 특정 타입을 확인하려면

switch내 케이스들에서 is나 as패턴을 사용해볼 수 있다.

 

아래 예시는 switch내의 쿼리에 대해 things 배열의 아이템들이 반복하고 있으며

이를 통해 각 아이템들의 타입을 확인할 수 있다.

 

// 공식문서 예시 참고하여 새로 작성함

for thing in everything {
    switch thing {
    case 5 as Int: print("five as an Int")
    case 5 as Double: print("five as an 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 album as Album: print("the \(album.artist)'s album is the best")
    case let stringConverter as (String) -> String: print(stringConverter("pH-1"))
    default: print("something else")
    }
}

// five as an Int
// a positive double value of 9.9
// an integer value of 26
// a positive double value of 3.14159
// a string value of "hoi"
// an (x, y) point at 1.0, 2.0
// the pH-1's album is the best
// Hey, pH-1

 

 

 

※ 참고

[1] SeSAC2 33회차 수업 / 2022.08.18

[2] https://developer.apple.com/documentation/swift/anyobject/

[3] https://docs.swift.org/swift-book/LanguageGuide/TypeCasting.html