[英]Invoking a generic function with a type variable conforming to a protocol
在一个泛型函数中,我想测试符合某个协议的给定对象是否为给定类型。 如果将具体的类类型作为参数传递给检查功能,则效果很好。 但是,当我为类型使用变量(使用三元运算符)时,出现错误:
无法使用类型为“
(AnyObject, of: P.Type)
”的参数列表调用“isObject
”
另外,将类型变量P.Protocol
为P.Protocol
也无济于事,因为:
在参数类型“
P.Protocol
”中,“P
”不符合预期的类型“P
”
protocol P {
static var descr: String {get}
}
class A: P {
static let descr = "class A"
}
class B: P {
static let descr = "class B"
}
class Test {
func isObject<T:P>(_ object: AnyObject, of type: T.Type) -> Bool {
print("descr: \(type.descr)")
return object is T
}
}
let a = A()
let type = (false ? A.self : B.self) as P.Type //as! P.Protocol
let test = Test()
test.isObject(a, of: type)
问题是,与通用占位符T
,当T
是协议类型P
, T.Type
是P.Protocol
不 P.Type
。 换句话说,它采用描述协议本身的元类型,而不是描述符合协议类型的元类型。 这种区别很重要,因为协议不符合自己 。
您的情况下的一种解决方案是在P.Type
元类型周围引入包装器,该包装器在P.Type
程序中使用通用占位符,以便为您存储闭包以执行is
check。
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)
}
}
这是我在对此问答的回答中展示的包装程序的专用版本,在该版本中,我还展示了如何在Apple平台上解除T.self == base
的限制(但此限制不应成为您的问题)案件)。
您现在可以像这样使用包装器:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.