协议字典Swift 4 [英] Dictionary of a protocol Swift 4

查看:63
本文介绍了协议字典Swift 4的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个称为playable的协议,该协议要求实现func play(). DamageDrawACard类均符合协议

I have a protocol called playable which requires implementation of func play(). Class Damage and DrawACard both conform to the protocol

protocol Playable: class {
    func play(game: Game, value: Int) -> Player
}


class Damage: Playable, Hashable, Equatable {

    var hashValue: Int = 1

    static func ==(lhs: Damage, rhs: Damage) -> Bool {
        return lhs.hashValue == rhs.hashValue
    }

    func play(game: Game, value: Int) -> Player {
        // do stuff
        return game.activePlayer
    }
}

class DrawACard: Playable, Equatable, Hashable {

    var hashValue: Int = 2

    static func ==(lhs: DrawACard, rhs: DrawACard) -> Bool {
        return lhs.hashValue == rhs.hashValue
    }

    func play(game: Game, value: Int) -> Player {
        // do stuff
        return game.activePlayer
    }
}

我的问题如下:

class Card {
    var id: Int
    var name: String
    var cost: Int
    var description: String
    var target: Target
    var abilities: [Playable: Int]
    var cardType: CardType

    init(id: Int, name: String, cost: Int, description: String, cardType: CardType, target: Target, abilities: [Playable: Int]) {
        self.id = id
        self.name = name
        self.cost = cost
        self.description = description
        self.cardType = cardType
        self.abilities = abilities
        self.target = target
    }
}

当尝试将协议作为键时,类abilities中的第6个变量引发错误.它给了我:Type 'Playable' does not conform to protocol 'Hashable'.

The 6th variable in the class abilities throws an error when I try to put a protocol as the key. It gives me: Type 'Playable' does not conform to protocol 'Hashable'.

我希望功能变量具有实现Playable的对象的键和Int的值,例如. abilities = [DrawACard: 5]

I want the abilities variable to have a key of an object that implements Playable and a value of Int, eg. abilities = [DrawACard: 5]

我该怎么做?

推荐答案

这种带有类继承的混合协议非常复杂.特定问题的答案是您不能直接这样做,因为如果使PlayableHashable一致,则不能将它们排列成一个数组.

This kind of mixing protocols with class inheritance is notoriously complicated. The answer to your specific issue is you can't directly, because if you make Playable conform to Hashable, you can't make an array of them.

最简单的解决方案是在此处不使用协议.只需进行一个抽象类. Swift在抽象类方面不是很擅长,但是它们会使大多数这些问题消失.

The simplest solution is don't use a protocol here. Just make an abstract class. Swift isn't very good at abstract classes, but they will make most of these problems go away.

鉴于您的具体情况,我可能还会考虑对Playable使用枚举而不是协议.这样可能会使事情变得更简单.

Given your specific case, I might also consider using an enum for Playable rather than a protocol. That would likely make things simpler.

从那里开始,解决方案变得更加复杂.例如,您可以按照我的 ClassSet 实验的方式创建一个ClassDictionary.或者,您可以构建一个类型擦除器.但这很丑.

From there, the solutions get a bit more complicated. For example, you could create a ClassDictionary along the lines of my ClassSet experiment. Or you can build a type-eraser. But it gets ugly.

您还可以考虑从类切换到结构,并摆脱Dictionary,而仅使用Array.如果Int的点是一个计数,则仅具有该结构的多个副本.如果Int的点是一个参数(例如有多大损害"),则该点应该在Damage结构中,而不是在字典中.

You could also consider switching from a class to a struct, and getting rid of the Dictionary, and just using an Array. If the point of the Int is a count, then just have multiple copies of the struct. If the point of the Int is a parameter (like "how much damage"), then that should be inside the Damage struct, not in a dictionary.

(不相关的注释,您的哈希值非常奇怪.它们会起作用,但这并不是哈希函数的作用.)

(Unrelated note, your hash values are very strange. They'll work, but this isn't how hashes are meant to function.)

作为我要进行此操作的一个示例,我看到了类似的内容:

As an example of where I'm going with this, I'm seeing something like:

protocol Playable {
    func play(game: Game) -> Player
}

struct Damage: Playable {
    let amount: Int

    func play(game: Game) -> Player {
        // do stuff
        return game.activePlayer
    }
}

struct DrawACard: Playable {
    func play(game: Game) -> Player {
        // do stuff
        return game.activePlayer
    }
}

struct Card {
    let id: Int
    let name: String
    let cost: Int
    let description: String
    let cardType: CardType
    let target: Target
    let abilities: [Playable]
}

// A card that inflicts one damage
let card = Card(id: 1,
                name: "Strike",
                cost: 1,
                description: "Strike 'em",
                cardType: CardType(),
                target: Target(),
                abilities: [Damage(amount: 1)])

这将所有内容故意转换为不可变的结构;我相信您在此描述的所有内容实际上都是值类型.

This switched everything to immutable structs on purpose; I believe everything you're describing here are really value types.

这篇关于协议字典Swift 4的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆