1

I want a collection of a protocol type: in this case I want a variable "party" to be an array of type GameCharacter so I can put all things that conform to GameCharacter inside it.

the code below produces the following error:

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

what's the problem here? how to do it right?


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
Asperi
  • 228,894
  • 20
  • 464
  • 690
user14534957
  • 336
  • 3
  • 10

2 Answers2

0

You should not inherit your protocol from Identifiable (which has generics) in this case, instead add id explicitly and then below (simplified) is compilable

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
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • could you explain why i should not inherit from Identifiable? – user14534957 Jul 21 '21 at 17:17
  • Because Identifiable has generics inside, so your protocol also became generics and protocols with generics are not allowed to be used in variable declarations as you want to do - that's why you got the error. If you want use your protocol in array then don't make it generics. – Asperi Jul 21 '21 at 18:50
  • Ok thanks, but with your solution - GameCharacter protocol not conforming to Identifiable - I'm not able to use the "party"-Array (of type Character) inside a ForEach like intended.. but ok I can of cause use id:\.name key path.. – user14534957 Jul 21 '21 at 18:54
  • You are able to use directly any property in ForEach as identifier, in your case it can be as `ForEach(party, id: \.id)` – Asperi Jul 21 '21 at 18:55
0

I believe Identifiable is a protocol with associated type. Unfortunately, Swift does not support what you are trying to achieve, yet.

Please refer Swift associated types and protocol inheritance and How to use generic protocol as a variable type for discussions around this topic. These links discuss on possible solutions as well.

Bharad
  • 86
  • 5