Swift -- type(of:)

  • 概述

type(of:) 用于获取值的动态类型,动态类型指的是元类型(MetaType)的值

func printInfo(_ value: Any) {
    let t = type(of: value)
    print("'\(value)' of type '\(t)'")
}

let integer: Any = 5 // integer的静态类型为Any
printInfo(integer) //'5' of type 'Int'

// integer的动态类型为Int

上述例子中integer的静态类型和动态类型并不一样,type(of:) 返回的是integer在运行时的类型

type(of:) 返回的动态类型可以是class, structure, enumerationconcrete metatypes (T.Type),也可以是 protocol, protocol compositionexistential metatype (P.Type),如果 type(of:) 的参数的静态类型是 class 或者实现了 protocol,可以使用其返回的动态类型访问 classprotocol 中定义的构造函数或静态成员

class Smiley {
    class var text: String {
        return ":)"
    }
}

class EmojiSmiley : Smiley {
     override class var text: String {
        return "😀"
    }
}

func printSmileyInfo(_ value: Smiley) {
    let smileyType = type(of: value)
    print("Smile!", smileyType.text)
}

let emojiSmiley = EmojiSmiley()
printSmileyInfo(emojiSmiley)
// Smile! 😀

上述例子中,emojiSmiley的动态类型为EmojiSmiley,所以访问 type(of:) 返回的动态类型中的静态成员得到的是 😀,而不是 :)

  • type(of:)在泛型上下文中的坑!

func printGenericInfo<T>(_ value: T) {
    let t = type(of: value)
    print("'\(value)' of type '\(t)'")
}

protocol P {}
extension String: P {}

let stringAsP: P = "Hello!"
printGenericInfo(stringAsP)
// 'Hello!' of type 'P'

上述代码的目的是获取 stringAsP 的动态类型 P.Type,即 String.self,但结果却是 P.Protocol,为什么呢?
这是因为 printGenericInfo<T>(:) 并没有约束泛型参数T是实现了协议P的类型,而 stringAsP 的静态类型是P,所以将 stringAsP 传入 printGenericInfo<T>(:) 会让编译器认为传入的参数是一个protocol而不是一个实现了protocol的类型,所以 type(of:) 只能返回该protocol的动态类型,即 P.Protocol,而不是 P.Type

如果需要在泛型上下文中获取传入值的动态类型,需要先将传入值转换成 Any

func betterPrintGenericInfo<T>(_ value: T) {
    let t = type(of: value as Any)
    print("'\(value)' of type '\(t)'")
}

betterPrintGenericInfo(stringAsP)
// 'Hello!' of type 'String'

关于 Metatype, concrete metatypes, existential metatype 的解读可以看看: Swift -- MetaType

  • 参考文献:

Swift -- type(of:)

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容