大器晩成

Any, AnyObject 본문

iOS/Swift 문법

Any, AnyObject

zerobugpark 2024. 12. 19. 16:02
  • 타입 캐스팅을 수행할 때 일반적으로 상속 관계에 있는 클래스들끼리만 캐스팅할 수 있습니다.
  • 상속 관계에 있지 않은 클래스 간에는 타입 캐스팅을 할 수 없으므로 억지로 캐스팅하려 하면 오류가 발생합니다. 하지만 상속관계에 있지 않아도 타입 캐스팅할 수 있는 예외가 있는데, Any와 AnyObject 타입을 사용할 때입니다.
  • Any와 AnyObject는 무엇이든 다 받아들일 수 있는 일종의 범용 타입입니다.
  • Any, AnyObject는 최상위 타입이기 때문에, 항상 다운캐스팅을 해서 사용해야 합니다.
  • 일반 타입을 Any, AnyObject로 업 캐스팅은 언제든지 가능합니다.
[Any]  [AnyObject] 
  • 기본 타입(Int, String, Bool, Double...) 등 포함, 커스텀 클래스, 구조체 열거형, 함수 타입을 포함하여 모든 타입의 인스턴스를 나타낼 수 있습니다. (옵셔널 타입도 포함)
  • 모든 클래스 타입의 인스턴스를 나타낼 수 있습니다.

 

Any

var some: Any = "Hello"

if let some = some as? String {
    some.count
}

some = 10
some = 3.2
  • [단점]: 저장된 타입의 메모리 구조를 알 수 없기 때문에, 항상 타입 캐스팅해서 사용해야 합니다.
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

class Person {
    var id = 0
    var name = "이름"
    var email = "abc@gmail.com"
    
    func walk() {
        print("사람이 걷는다.")
    }
}


class Student{
    var studentId = 1

}



class Undergraduate {

    var major = "전공"

}



let array: [AnyObject] = [Person(), Student(), Undergraduate()]
(array[0] as! Person).name
  • AnyObject도 프로퍼티에 접근하기 위해서는 타입 캐스팅을 사용해야 합니다.
  • 클래스 타입만 가능하며, 클래스 타입이 아닌 경우에는 오류가 발생합니다.

 

Apple 공식문서

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

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 또는 AnyObject 타입으로만 알려진 상수 또는 변수의 특정 타입을 알아보려면 switch 구문의 케이스로 is 또는 as 패턴을 사용할 수 있습니다. 아래의 예제는 things 배열에 항목을 반복하고 switch 구문으로 각 항목의 타입을 조회합니다. 몇몇의 switch 구문의 케이스는 일치된 값을 지정된 타입의 상수에 바인딩하여 해당 값을 출력할 수 있도록 합니다:
 
옵셔널 값의 Any 변환
let optionalNumber: Int? = 3
things.append(optionalNumber)        // Warning
things.append(optionalNumber as Any) // No warning​
  • Any타입으로 변환하면 컴파일러가 알려주는 경고를 없앨 수 있습니다.
  • 옵셔널은 임시적인 값이어서, 개발자들에게 언래핑을 해서 사용해야 한다고 경고를 통해 알려주고 있습니다.
  • 하지만 Any로 변환하겠다는 것은 그 자체를 사용하겠다는 의미로 경고를 사라지게 할 수 있습니다.
728x90

'iOS > Swift 문법' 카테고리의 다른 글

[Extensions] 멤버의 확장 (계산 속성)  (0) 2024.12.23
[Extensions] 확장  (0) 2024.12.23
타입과 다형성  (0) 2024.12.19
타입캐스팅 (as, type cast operator)  (0) 2024.12.19
타입캐스팅(Type Casting)  (0) 2024.12.19