Быстрое стирание типа для протокола с требованием типа Self - PullRequest
1 голос
/ 18 апреля 2019

Я пытаюсь создать простой игровой движок для забавных и образовательных целей.У меня есть протокол 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!
}

Протокол «Сущность» можно использовать только в качестве общего ограничения, поскольку он имеет собственные требования или требования к связанному типу

IЯ не уверен, как это исправить, так как я не могу сделать это путем определения стирания типа (как в случае EntityComponent).

Буду признателен за любые подсказки и идеи!

1 Ответ

0 голосов
/ 18 апреля 2019

Это может помочь удалить требование связанного типа и использовать вместо него дженерики:

protocol EntityComponent {
    func update<T: Entity>(_ entity: T, deltaTime seconds: TimeInterval)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...