【问题标题】:Swift type comparison against stored typeSwift 类型与存储类型的比较
【发布时间】:2020-12-30 19:06:21
【问题描述】:

我有一个类将类型收集到一个数组中,然后确定一个对象是否属于其中一种类型:

struct Item: Hashable {}

class TypeChecker {
    let typeCollection: [Any.Type] = [Item.self]
    
    func acceptObject(_ object: Any) -> Bool {
        typeCollection.contains(where: { type(of: object) == $0 })
    }
}

let checker = TypeChecker()

let object1: Item = Item()
checker.acceptObject(object1) // returns true

let object2: AnyHashable = Item()
checker.acceptObject(object2) // returns false

在上面的简化片段中,显式输入 object1 可以正常工作,但是,抽象输入 object2 失败。是什么赋予了?我将如何修复 TypeChecker?

【问题讨论】:

  • 在第二种情况下,您已将对象声明为 AnyHashable 类型,因此编译器将接受符合 AnyHashable 的任何类型的对象,并将其视为 AnyHashable 而不是 Item。请注意,let object3 = Item() 将返回 true
  • 有趣的是,如果你有一个协议类型而不是AnyHashable,你的函数将返回正确的结果。 (参见type(of:) 文档的最后一部分)显然这不起作用,因为AnyHashableItem 结构实际上没有实现的具体类型。

标签: swift types


【解决方案1】:

方法 1:在编译时已知可接受的类型。

创建一个标记协议并为可接受的类型添加一致性:

protocol AcceptableForSomeActionType { }

extension Item: AcceptableForSomeActionType { }

class TypeChecker {
    func acceptObject(_ object: Any) -> Bool {
        object is AcceptableForSomeActionType
    }
}

方法 2:在运行时已知可接受的类型时。

为提供真实对象类型的容器类型创建协议。

protocol ObjectContainer {
    var objectType: Any.Type { get }
}

extension AnyHashable: ObjectContainer {
    var objectType: Any.Type { type(of: base) }
}

class TypeChecker {
    private let typeIdentifiers: Set<ObjectIdentifier> = [ObjectIdentifier(Item.self)]

    func acceptObject(_ object: Any) -> Bool {
        let objectType = (object as? ObjectContainer)?.objectType ?? type(of: object)
        return typeIdentifiers.contains(ObjectIdentifier(objectType))
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-10
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多