强制模板成为协议



如何确保给定的模板参数是协议?

GKEntity有一个名为component(ofType: class)的函数,我想添加component(ofProtocol: Protocol)。它看起来像这样:

extension GKEntity {
func component<T: Protocol>(ofProtocol: T) -> T? {
return self.components.first() { component in
return component.conforms(to: ofProtocol)
} as? T
}
}

我想在包含对实体的引用的组件中使用它,如下所示:

let component = self.entity?.component(ofProtocol: SpriteComponentProtocol)

但不知何故,我总是得到:

显示所有消息

Cannot convert value of type 'SpriteComponentProtocol.Protocol' to expected argument type 'Protocol'

更新:

这个想法是我有一个雪碧组件:

protocol SpriteComponentProtocol {
var spriteNode: SKSpriteNode { get set }
}
class SpriteComponent: GKComponent {
var spriteNode: SKSpriteNode?
}

以及控件的另一个组件:

protocol PlayerControlComponentProtocol {
var steerAngle: Double { get set }
}
class PlayerControlComponent: GKComponent, PlayerControlComponentProtocol {
var steerAngle: Double = 90.0
override func update(deltaTime seconds: TimeInterval) {
//here i do manipulate the spriteComponent.spriteNode
let comp = self.entity?.component(ofProtocol: SpriteComponentProtocol)
}
}

我希望能够随时更换精灵组件。

代码的问题在于Protocol是描述 Obj-C 协议的不透明类型,因此如果要将SpriteComponentProtocol.self桥接到它,则需要将SpriteComponentProtocol标记为@objc(但即使你这样做了;你也无法强制转换为T,因为返回的实例不是类型Protocol(。

但话虽如此,您不需要在此处使用 Obj-CProtocol类型或conforms(to:)方法,您只需在component(ofType:)重载中使用条件类型转换运算符as?而无需T进行GKComponent约束:

extension GKEntity {
func component<T>(ofType type: T.Type) -> T? {
return self.components.lazy.flatMap{ $0 as? T }.first
}
}

我们在这里使用lazy以避免评估所有components,然后flatMap(_:)first以获得第一个可铸造T的元素(在T是协议类型的情况下,这给了我们第一个符合协议的元素(。

然后,您可以像这样简单地使用它:

protocol SpriteComponentProtocol {
var spriteNode: SKSpriteNode { get set }
}
class PlayerControlComponent: GKComponent {
override func update(deltaTime seconds: TimeInterval) {
let comp = self.entity?.component(ofType: SpriteComponentProtocol.self)
}
}

在 Swift 4 中,你可以完全删除这个重载,而是简单地用类存在元类型调用GKEntitycomponent(ofType:)方法:

let comp = self.entity?.component(ofType: (GKComponent & SpriteComponentProtocol).self)

就像现在一样,T满足: GKComponent约束。然后,您可以在解包的实例上访问GKComponent方法和SpriteComponentProtocol协议要求。

相关内容

  • 没有找到相关文章

最新更新