具有 self 类型要求的协议(protocol)的 Swift 类型删除

标签 swift generics protocols type-erasure

我正在尝试设计一个用于娱乐和教育目的的简单游戏引擎。我有一个代表我的游戏的 Game 协议(protocol)和代表一个实体(比如玩家或对手)的 Entity 协议(protocol)。最后,我有一个 EntityComponent 协议(protocol),它的实现更新了一个 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)的编译错误:

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

Protocol 'EntityComponent' can only be used as a generic constraint because it has Self or associated type requirements

这个问题可以通过为 EntityComponent 协议(protocol)定义类型删除并像这样更新 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 协议(protocol)中的更改会产生另一个问题。这次在 Game 协议(protocol)中:

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

Protocol 'Entity' can only be used as a generic constraint because it has Self or associated type requirements

我不确定如何解决这个问题,因为我无法通过定义类型删除来解决这个问题(如 EntityComponent 的情况)。

我将不胜感激任何提示和想法!

最佳答案

它可能有助于删除关联的类型要求并改用泛型:

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

关于具有 self 类型要求的协议(protocol)的 Swift 类型删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55736034/

相关文章:

swift - 如果在扩展中实现协议(protocol)方法,是否需要在协议(protocol)中指定方法?

ios - UIActivityIndi​​catorView 对话框概览

ios - 如何更好地发送完整的闭包

java - 接口(interface)与泛型?

c# - 我可以捕获 C# 中泛型参数传入的类型的异常吗?

arrays - Swift3 - 扩展类型 Collection 的问题

c - 数据包的协议(protocol)

ios - 导航栏右栏按钮项目间距

ios - 带有参数的 Swift 类型反射初始化

java - 如何直接调用泛型方法?