Swift 使用符合协议的类型变量调用泛型函数

Swift 使用符合协议的类型变量调用泛型函数,swift,generics,Swift,Generics,在泛型函数中,我想测试符合特定协议的给定对象是否属于给定类型。如果将一个具体的类类型作为参数传递给checking函数,效果会非常好。但是,当我对类型使用变量(使用三元运算符)时,我得到一个错误: 无法使用类型为“(AnyObject,of:p.type)”的参数列表调用“isObject” 另外将类型变量强制转换为p.Protocol也没有帮助,因为: 在参数类型“p.Protocol”中,“p”与预期类型“p”不符 协议P{ 静态变量描述:字符串{get} } 甲级:P{ 静态let des

在泛型函数中,我想测试符合特定协议的给定对象是否属于给定类型。如果将一个具体的类类型作为参数传递给checking函数,效果会非常好。但是,当我对类型使用变量(使用三元运算符)时,我得到一个错误:

无法使用类型为“
(AnyObject,of:p.type)”的参数列表调用“
isObject

另外将类型变量强制转换为
p.Protocol
也没有帮助,因为:

在参数类型“
p.Protocol
”中,“
p
”与预期类型“
p
”不符

协议P{
静态变量描述:字符串{get}
}
甲级:P{
静态let descr=“A类”
}
B类:P{
静态let descr=“B类”
}
课堂测试{
func isObject(object:AnyObject,类型:T.type)->Bool{
打印(“descr:\(type.descr)”)
返回对象是T
}
}
设a=a()
设type=(false?A.self:B.self)为P.type//as!P.议定书
let test=test()
试验.等深线(a,类型:类型)

问题在于,对于通用占位符
T
,当
T
是协议类型
p
时,
T.type
p.protocol
而不是
p.type
。换句话说,它采用描述协议本身的元类型,而不是描述符合协议的类型的元类型。这一区别很重要,因为

在您的案例中,一个解决方案是在
p.Type
元类型周围引入一个包装器,它在初始化器中使用一个通用占位符来存储闭包,以便为您执行
is
检查

struct AnyPType {

    let base: P.Type
    private let _isInstance: (Any) -> Bool

    /// Creates a new AnyType wrapper from a given metatype.
    /// The passed metatype's value **must** match its static value, i.e `T.self == base`.
    init<T : P>(_ base: T.Type) {
        precondition(T.self == base, "The static value \(T.self) and dynamic value \(base) of the passed metatype do not match")
        self.base = T.self
        self._isInstance = { $0 is T }
    }

    func isInstance(_ instance: Any) -> Bool {
        return _isInstance(instance)
    }
}

问题是,对于通用占位符
T
,当
T
是协议类型
p
时,
T.type
p.protocol
而不是
p.type
。换句话说,它采用描述协议本身的元类型,而不是描述符合协议的类型的元类型。这一区别很重要,因为

在您的案例中,一个解决方案是在
p.Type
元类型周围引入一个包装器,它在初始化器中使用一个通用占位符来存储闭包,以便为您执行
is
检查

struct AnyPType {

    let base: P.Type
    private let _isInstance: (Any) -> Bool

    /// Creates a new AnyType wrapper from a given metatype.
    /// The passed metatype's value **must** match its static value, i.e `T.self == base`.
    init<T : P>(_ base: T.Type) {
        precondition(T.self == base, "The static value \(T.self) and dynamic value \(base) of the passed metatype do not match")
        self.base = T.self
        self._isInstance = { $0 is T }
    }

    func isInstance(_ instance: Any) -> Bool {
        return _isInstance(instance)
    }
}
class Test {
    func isObject(_ object: Any, of type: AnyPType) -> Bool {
        print("descr: \(type.base.descr)")
        return type.isInstance(object)
    }
}

let type = AnyPType(A.self) // or AnyPType(B.self)

print(Test().isObject(A(), of: type))

// descr: class A
// true