美文网首页js css htmlSwift
Swift中的Any、AnyObject、AnyClass介绍

Swift中的Any、AnyObject、AnyClass介绍

作者: 喔牛慢慢爬 | 来源:发表于2022-06-01 14:12 被阅读0次

    概念

    • AnyObject:可以表示任何类类型的对象实例,所有类都隐式地遵循 AnyObject;
    • Any:可以表示任何类型,包括基础数据类型、枚举类型、结构体、函数类型等;
    • AnyClass:表示类的元类型,是AnyObject.Type的别名:定义typealias AnyClass = AnyObject.Type;

    我们可以说AnyObject是Any的子集,Any和AnyObject都是Swift 的不确定的类型。

    Any类型

    • 类、结构体或者枚举;
    • 元类型,比如 Int.self ;
    • 带有任意类型元素的元组;
    • 闭包或者函数类型。
    let mixed: [Any] = ["one", 2, true, (4, 5.3), { () -> Int in return 6 }]
    

    当你使用 Any 作为实例的具体类型时,你需要在访问其属性和方法之前把它转换成已知类型

    if let first = mixed.first as? String {
        print("The first item, '\(first)', is a string.")
    }
    // Prints "The first item, 'one', is a string."
    

    AnyObject类型

    所有类都隐式遵循AnyObject协议,这也限制了AnyObject是只适用于Class类型的原因。AnyObject与OC中的id一样,它可以表示任意类的实例,译器不会对向声明为 id 的变量进行类型检查。因此,导入的OC类型经常使用AnyObject作为属性、方法参数和返回值的类型。

    因为在Swift中的String,Array等类型都是struct类型定义的了,变成了值类型,与OC中的引用类型不同,并不能是AnyObject来表示。因此在混编时需要使用AnyObject类型将Swift的值类型来转化为OC的引用类型。

    看下面的例子:

    let s: AnyObject = "This is a bridged string." as NSString
    print(s is NSString)
    // Prints "true"
    
    let v: AnyObject = 100 as NSNumber
    print(type(of: v))
    // Prints "__NSCFNumber"
    

    再看一个例子

    let swiftInt: Int? = 1
    let swiftString: String = "miao"
            
    var array: [AnyObject] = []
    array.append(swiftInt as AnyObject) //Int,Array是结构体,任意类型用Any,所以类型不符合,要强转类型
    array.append(swiftString as AnyObject)
    

    我们在这里声明了一个 Int 和一个 String,按理说它们都应该只能被 Any 代表,而不能被 AnyObject 代表的。但是你会发现这段代码是可以编译运行通过的。那是不是说其实 Apple 的编程指南出错了呢?不是这样的,你可以打印一下 array,就会发现里面的元素其实已经变成了 NSNumber 和 NSString 了,这里发生了一个自动的转换。在 Swift 和 Cocoa 中的这几个对应的类型是可以进行自动转换的。因为我们显式地声明了需要 AnyObject,编译器认为我们需要的的是 Cocoa 类型而非原生类型,而帮我们进行了自动的转换。

    AnyClass

    所有类类型隐式遵守AnyClass协议

    属于AnyObject.Type的别名:typealias AnyClass = AnyObject .Type

    通过AnyObject.Type这种方式所得到的是一个元类型(Meta),声明时我们总是在类型的名称后面加上.Type,比如 A.Type 代表的是 A 这个类型的类型。也就是说,我们可以声明一个元类型来存储 A 这个类型本身,而在从 A 中取出其类型时,我们需要使用到 .self

    class A {
        class func method() {
            print("Hello")
        }
    }
    
    let typeA: A.Type = A.self
    typeA,method()
    或
    let typeA: AnyClass = A.self
    (typeA as! A.Type).method()
    
    

    注:其实在 Swift 中,.self 可以用在类型后面取得类型本身,也可以用在某个实例后面取得这个实例本身。前一种方法可以用来获得一个表示该类型的值,这在某些时候会很有用;而后者因为拿到的实例本身,所以暂时似乎没有太多需要这么使用的案例。

    使用示例1

    class IntegerRef {
        @objc class func getDefaultValue() -> Int {
            return 42
        }
    }
    
    func getDefaultValue(_ c: AnyClass) -> Int? {
        return c.getDefaultValue?()
    }
    
    print(getDefaultValue(IntegerRef.self))
    // Prints "Optional(42)"
    print(getDefaultValue(NSString.self))
    // Prints "nil"
    

    使用示例2

    class MusicViewController: UIViewController {
    
    }
    
    class AlbumViewController: UIViewController {
    
    }
    let usingVCTypes: [AnyClass] = [MusicViewController.self,
        AlbumViewController.self]
    func setupViewControllers(vcTypes: [AnyClass]) {
        for vcType in vcTypes {
            if vcType is UIViewController.Type {
                let vc = (vcType as! UIViewController.Type).init()
                print(vc)
            }
        }
    }
    setupViewControllers(usingVCTypes)
    

    .Type 表示的是某个类型的元类型,而在 Swift 中,除了 class,struct 和 enum 这三个类型外,我们还可以定义 protocol。对于 protocol 来说,有时候我们也会想取得接口的元类型。这时我们可以在某个 protocol 的名字后面使用 .Protocol 来获取,使用的方法和 .Type 是类似的。

    参考文献

    相关文章

      网友评论

        本文标题:Swift中的Any、AnyObject、AnyClass介绍

        本文链接:https://www.haomeiwen.com/subject/byexmrtx.html