带有自我类型要求的协议的快速类型擦除

时间:2019-04-17 21:12:08

标签: swift generics protocols type-erasure

我正在尝试设计一个简单的游戏引擎,以达到娱乐和教育目的。我有一个Game协议代表我的游戏,有一个Entity协议代表一个实体(例如玩家或对手)。最后,我有一个EntityComponent协议,该协议的实现更新了Entity。在Swift中看起来像这样:

protocol Game {
    var entities: [Entity] { get }
}

protocol Entity {
    var components: [EntityComponent] { get }
}

protocol EntityComponent {
    func update(_ entity: Entity, deltaTime seconds: TimeInterval)
}

我希望使用它们更新的实体来概括我的实体组件。在Swift中,我可以使用associatedtype

protocol EntityComponent {
    associatedtype EntityType: Entity
    func update(_ entity: EntityType, deltaTime seconds: TimeInterval)
}

但是,这会为Entity协议产生一个编译错误:

protocol Entity {
    var components: [EntityComponent] { get } // ERROR!
}
  

协议“ EntityComponent”仅具有通用或相关类型要求,因此只能用作通用约束

可以通过为EntityComponent协议定义类型擦除并更新Entity来解决此问题:

protocol Entity {
    var components: [AnyEntityComponent<Self>] { get }
}

final class AnyEntityComponent<EntityType: Entity>: EntityComponent {
    init<T: EntityComponent>(_ component: T) where T.EntityType == EntityType {
        self.update = component.update
    }

    func update(_ entity: EntityType, deltaTime seconds: TimeInterval) {
        update(entity, seconds)
    }

    private let update: (EntityType, TimeInterval) -> Void
}

不幸的是,Entity协议中的更改产生了另一个问题。这次使用Game协议:

protocol Game {
    var entities: [Entity] { get } // ERROR!
}
  

协议“实体”只能用作通用约束,因为它具有“自我”或关联的类型要求

我不确定如何解决此问题,因为我无法通过定义类型擦除来解决(例如EntityComponent)。

我将不胜感激!

1 个答案:

答案 0 :(得分:0)

删除相关的类型要求并改用泛型可能会有所帮助:

protocol EntityComponent {
    func update<T: Entity>(_ entity: T, deltaTime seconds: TimeInterval)
}