【问题标题】:Collections of Protocol Types - protocol oriented programming协议类型的集合 - 面向协议的编程
【发布时间】:2021-07-22 00:09:56
【问题描述】:

我想要一个协议类型的集合:在这种情况下,我想要一个变量“party”是一个 GameCharacter 类型的数组,这样我就可以将所有符合 GameCharacter 的东西放入其中。

下面的代码产生以下错误:

Protocol 'GameCharacter' 只能用作通用约束,因为 它有 Self 或关联的类型要求

这里有什么问题?怎么做才对?


protocol GameCharacter: Identifiable {
    var name: String {get}
    var maxHealt: Int {get}
    var healt: Int { get set }

    }

struct Warrior: GameCharacter, Fighter {
    var name: String
    var maxHealt: Int
    var healt: Int
    var armor: Armor
    var weapon: Weapon
    var resistence: Int
    var id: String {
        return name
    }
}

var party: [GameCharacter] <--- error

【问题讨论】:

    标签: swift collections protocols identifiable


    【解决方案1】:

    在这种情况下,您不应从Identifiable(具有泛型)继承您的协议,而是显式添加id,然后在下面(简化)是可编译的

    protocol GameCharacter {
        var id: String { get }     // << here !!
        var name: String {get}
        var maxHealt: Int {get}
        var healt: Int { get set }
        
    }
    
    struct Warrior: GameCharacter {
        var name: String
        var maxHealt: Int
        var healt: Int
        var resistence: Int
        var id: String {        // << here !!
            return name
        }
    }
    

    【讨论】:

    • 你能解释一下为什么我不应该从 Identifiable 继承吗?
    • 因为 Identifiable 内部有泛型,所以你的协议也变成了泛型,并且不允许在变量声明中使用具有泛型的协议 - 这就是你得到错误的原因。如果你想在数组中使用你的协议,那么不要让它泛型。
    • 好的,谢谢,但是使用您的解决方案 - GameCharacter 协议不符合 Identifiable - 我无法在 ForEach 中使用“party”-Array(字符类型),如预期的那样......但没关系我可以使用 id:\.name key path..
    • 您可以直接使用 ForEach 中的任何属性作为标识符,在您的情况下可以是 ForEach(party, id: \.id)
    【解决方案2】:

    我相信Identifiable 是一个具有关联类型的协议。不幸的是,Swift 不支持您想要实现的目标,目前

    请参阅Swift associated types and protocol inheritanceHow to use generic protocol as a variable type 以了解有关此主题的讨论。这些链接也讨论了可能的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多